6666#include "nfs4idmap.h"
6767#include "nfs4session.h"
6868#include "fscache.h"
69+ #include "nfs42.h"
6970
7071#include "nfs4trace.h"
7172
@@ -7440,6 +7441,103 @@ nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len)
74407441
74417442#endif
74427443
7444+ #ifdef CONFIG_NFS_V4_2
7445+ static int nfs4_xattr_set_nfs4_user (const struct xattr_handler * handler ,
7446+ struct dentry * unused , struct inode * inode ,
7447+ const char * key , const void * buf ,
7448+ size_t buflen , int flags )
7449+ {
7450+ struct nfs_access_entry cache ;
7451+
7452+ if (!nfs_server_capable (inode , NFS_CAP_XATTR ))
7453+ return - EOPNOTSUPP ;
7454+
7455+ /*
7456+ * There is no mapping from the MAY_* flags to the NFS_ACCESS_XA*
7457+ * flags right now. Handling of xattr operations use the normal
7458+ * file read/write permissions.
7459+ *
7460+ * Just in case the server has other ideas (which RFC 8276 allows),
7461+ * do a cached access check for the XA* flags to possibly avoid
7462+ * doing an RPC and getting EACCES back.
7463+ */
7464+ if (!nfs_access_get_cached (inode , current_cred (), & cache , true)) {
7465+ if (!(cache .mask & NFS_ACCESS_XAWRITE ))
7466+ return - EACCES ;
7467+ }
7468+
7469+ if (buf == NULL )
7470+ return nfs42_proc_removexattr (inode , key );
7471+ else
7472+ return nfs42_proc_setxattr (inode , key , buf , buflen , flags );
7473+ }
7474+
7475+ static int nfs4_xattr_get_nfs4_user (const struct xattr_handler * handler ,
7476+ struct dentry * unused , struct inode * inode ,
7477+ const char * key , void * buf , size_t buflen )
7478+ {
7479+ struct nfs_access_entry cache ;
7480+
7481+ if (!nfs_server_capable (inode , NFS_CAP_XATTR ))
7482+ return - EOPNOTSUPP ;
7483+
7484+ if (!nfs_access_get_cached (inode , current_cred (), & cache , true)) {
7485+ if (!(cache .mask & NFS_ACCESS_XAREAD ))
7486+ return - EACCES ;
7487+ }
7488+
7489+ return nfs42_proc_getxattr (inode , key , buf , buflen );
7490+ }
7491+
7492+ static ssize_t
7493+ nfs4_listxattr_nfs4_user (struct inode * inode , char * list , size_t list_len )
7494+ {
7495+ u64 cookie ;
7496+ bool eof ;
7497+ int ret , size ;
7498+ char * buf ;
7499+ size_t buflen ;
7500+ struct nfs_access_entry cache ;
7501+
7502+ if (!nfs_server_capable (inode , NFS_CAP_XATTR ))
7503+ return 0 ;
7504+
7505+ if (!nfs_access_get_cached (inode , current_cred (), & cache , true)) {
7506+ if (!(cache .mask & NFS_ACCESS_XALIST ))
7507+ return 0 ;
7508+ }
7509+
7510+ cookie = 0 ;
7511+ eof = false;
7512+ buflen = list_len ? list_len : XATTR_LIST_MAX ;
7513+ buf = list_len ? list : NULL ;
7514+ size = 0 ;
7515+
7516+ while (!eof ) {
7517+ ret = nfs42_proc_listxattrs (inode , buf , buflen ,
7518+ & cookie , & eof );
7519+ if (ret < 0 )
7520+ return ret ;
7521+
7522+ if (list_len ) {
7523+ buf += ret ;
7524+ buflen -= ret ;
7525+ }
7526+ size += ret ;
7527+ }
7528+
7529+ return size ;
7530+ }
7531+
7532+ #else
7533+
7534+ static ssize_t
7535+ nfs4_listxattr_nfs4_user (struct inode * inode , char * list , size_t list_len )
7536+ {
7537+ return 0 ;
7538+ }
7539+ #endif /* CONFIG_NFS_V4_2 */
7540+
74437541/*
74447542 * nfs_fhget will use either the mounted_on_fileid or the fileid
74457543 */
@@ -10045,7 +10143,7 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = {
1004510143
1004610144static ssize_t nfs4_listxattr (struct dentry * dentry , char * list , size_t size )
1004710145{
10048- ssize_t error , error2 ;
10146+ ssize_t error , error2 , error3 ;
1004910147
1005010148 error = generic_listxattr (dentry , list , size );
1005110149 if (error < 0 )
@@ -10058,7 +10156,17 @@ static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
1005810156 error2 = nfs4_listxattr_nfs4_label (d_inode (dentry ), list , size );
1005910157 if (error2 < 0 )
1006010158 return error2 ;
10061- return error + error2 ;
10159+
10160+ if (list ) {
10161+ list += error2 ;
10162+ size -= error2 ;
10163+ }
10164+
10165+ error3 = nfs4_listxattr_nfs4_user (d_inode (dentry ), list , size );
10166+ if (error3 < 0 )
10167+ return error3 ;
10168+
10169+ return error + error2 + error3 ;
1006210170}
1006310171
1006410172static const struct inode_operations nfs4_dir_inode_operations = {
@@ -10146,10 +10254,21 @@ static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
1014610254 .set = nfs4_xattr_set_nfs4_acl ,
1014710255};
1014810256
10257+ #ifdef CONFIG_NFS_V4_2
10258+ static const struct xattr_handler nfs4_xattr_nfs4_user_handler = {
10259+ .prefix = XATTR_USER_PREFIX ,
10260+ .get = nfs4_xattr_get_nfs4_user ,
10261+ .set = nfs4_xattr_set_nfs4_user ,
10262+ };
10263+ #endif
10264+
1014910265const struct xattr_handler * nfs4_xattr_handlers [] = {
1015010266 & nfs4_xattr_nfs4_acl_handler ,
1015110267#ifdef CONFIG_NFS_V4_SECURITY_LABEL
1015210268 & nfs4_xattr_nfs4_label_handler ,
10269+ #endif
10270+ #ifdef CONFIG_NFS_V4_2
10271+ & nfs4_xattr_nfs4_user_handler ,
1015310272#endif
1015410273 NULL
1015510274};
0 commit comments