66
66
#include "nfs4idmap.h"
67
67
#include "nfs4session.h"
68
68
#include "fscache.h"
69
+ #include "nfs42.h"
69
70
70
71
#include "nfs4trace.h"
71
72
@@ -7440,6 +7441,103 @@ nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len)
7440
7441
7441
7442
#endif
7442
7443
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
+
7443
7541
/*
7444
7542
* nfs_fhget will use either the mounted_on_fileid or the fileid
7445
7543
*/
@@ -10045,7 +10143,7 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = {
10045
10143
10046
10144
static ssize_t nfs4_listxattr (struct dentry * dentry , char * list , size_t size )
10047
10145
{
10048
- ssize_t error , error2 ;
10146
+ ssize_t error , error2 , error3 ;
10049
10147
10050
10148
error = generic_listxattr (dentry , list , size );
10051
10149
if (error < 0 )
@@ -10058,7 +10156,17 @@ static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
10058
10156
error2 = nfs4_listxattr_nfs4_label (d_inode (dentry ), list , size );
10059
10157
if (error2 < 0 )
10060
10158
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 ;
10062
10170
}
10063
10171
10064
10172
static const struct inode_operations nfs4_dir_inode_operations = {
@@ -10146,10 +10254,21 @@ static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
10146
10254
.set = nfs4_xattr_set_nfs4_acl ,
10147
10255
};
10148
10256
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
+
10149
10265
const struct xattr_handler * nfs4_xattr_handlers [] = {
10150
10266
& nfs4_xattr_nfs4_acl_handler ,
10151
10267
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
10152
10268
& nfs4_xattr_nfs4_label_handler ,
10269
+ #endif
10270
+ #ifdef CONFIG_NFS_V4_2
10271
+ & nfs4_xattr_nfs4_user_handler ,
10153
10272
#endif
10154
10273
NULL
10155
10274
};
0 commit comments