32
32
#include "cifs_unicode.h"
33
33
34
34
#define MAX_EA_VALUE_SIZE CIFSMaxBufSize
35
- #define CIFS_XATTR_CIFS_ACL "system.cifs_acl"
35
+ #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" /* DACL only */
36
+ #define CIFS_XATTR_CIFS_NTSD "system.cifs_ntsd" /* owner plus DACL */
36
37
#define CIFS_XATTR_ATTRIB "cifs.dosattrib" /* full name: user.cifs.dosattrib */
37
38
#define CIFS_XATTR_CREATETIME "cifs.creationtime" /* user.cifs.creationtime */
38
39
/*
39
40
* Although these three are just aliases for the above, need to move away from
40
41
* confusing users and using the 20+ year old term 'cifs' when it is no longer
41
42
* secure, replaced by SMB2 (then even more highly secure SMB3) many years ago
42
43
*/
43
- #define SMB3_XATTR_CIFS_ACL "system.smb3_acl"
44
+ #define SMB3_XATTR_CIFS_ACL "system.smb3_acl" /* DACL only */
45
+ #define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd" /* owner plus DACL */
44
46
#define SMB3_XATTR_ATTRIB "smb3.dosattrib" /* full name: user.smb3.dosattrib */
45
47
#define SMB3_XATTR_CREATETIME "smb3.creationtime" /* user.smb3.creationtime */
46
48
/* BB need to add server (Samba e.g) support for security and trusted prefix */
47
49
48
- enum { XATTR_USER , XATTR_CIFS_ACL , XATTR_ACL_ACCESS , XATTR_ACL_DEFAULT };
50
+ enum { XATTR_USER , XATTR_CIFS_ACL , XATTR_ACL_ACCESS , XATTR_ACL_DEFAULT ,
51
+ XATTR_CIFS_NTSD };
52
+
53
+ static int cifs_attrib_set (unsigned int xid , struct cifs_tcon * pTcon ,
54
+ struct inode * inode , char * full_path ,
55
+ const void * value , size_t size )
56
+ {
57
+ ssize_t rc = - EOPNOTSUPP ;
58
+ __u32 * pattrib = (__u32 * )value ;
59
+ __u32 attrib ;
60
+ FILE_BASIC_INFO info_buf ;
61
+
62
+ if ((value == NULL ) || (size != sizeof (__u32 )))
63
+ return - ERANGE ;
64
+
65
+ memset (& info_buf , 0 , sizeof (info_buf ));
66
+ attrib = * pattrib ;
67
+ info_buf .Attributes = cpu_to_le32 (attrib );
68
+ if (pTcon -> ses -> server -> ops -> set_file_info )
69
+ rc = pTcon -> ses -> server -> ops -> set_file_info (inode , full_path ,
70
+ & info_buf , xid );
71
+ if (rc == 0 )
72
+ CIFS_I (inode )-> cifsAttrs = attrib ;
73
+
74
+ return rc ;
75
+ }
76
+
77
+ static int cifs_creation_time_set (unsigned int xid , struct cifs_tcon * pTcon ,
78
+ struct inode * inode , char * full_path ,
79
+ const void * value , size_t size )
80
+ {
81
+ ssize_t rc = - EOPNOTSUPP ;
82
+ __u64 * pcreation_time = (__u64 * )value ;
83
+ __u64 creation_time ;
84
+ FILE_BASIC_INFO info_buf ;
85
+
86
+ if ((value == NULL ) || (size != sizeof (__u64 )))
87
+ return - ERANGE ;
88
+
89
+ memset (& info_buf , 0 , sizeof (info_buf ));
90
+ creation_time = * pcreation_time ;
91
+ info_buf .CreationTime = cpu_to_le64 (creation_time );
92
+ if (pTcon -> ses -> server -> ops -> set_file_info )
93
+ rc = pTcon -> ses -> server -> ops -> set_file_info (inode , full_path ,
94
+ & info_buf , xid );
95
+ if (rc == 0 )
96
+ CIFS_I (inode )-> createtime = creation_time ;
97
+
98
+ return rc ;
99
+ }
49
100
50
101
static int cifs_xattr_set (const struct xattr_handler * handler ,
51
102
struct dentry * dentry , struct inode * inode ,
@@ -86,6 +137,23 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
86
137
87
138
switch (handler -> flags ) {
88
139
case XATTR_USER :
140
+ cifs_dbg (FYI , "%s:setting user xattr %s\n" , __func__ , name );
141
+ if ((strcmp (name , CIFS_XATTR_ATTRIB ) == 0 ) ||
142
+ (strcmp (name , SMB3_XATTR_ATTRIB ) == 0 )) {
143
+ rc = cifs_attrib_set (xid , pTcon , inode , full_path ,
144
+ value , size );
145
+ if (rc == 0 ) /* force revalidate of the inode */
146
+ CIFS_I (inode )-> time = 0 ;
147
+ break ;
148
+ } else if ((strcmp (name , CIFS_XATTR_CREATETIME ) == 0 ) ||
149
+ (strcmp (name , SMB3_XATTR_CREATETIME ) == 0 )) {
150
+ rc = cifs_creation_time_set (xid , pTcon , inode ,
151
+ full_path , value , size );
152
+ if (rc == 0 ) /* force revalidate of the inode */
153
+ CIFS_I (inode )-> time = 0 ;
154
+ break ;
155
+ }
156
+
89
157
if (cifs_sb -> mnt_cifs_flags & CIFS_MOUNT_NO_XATTR )
90
158
goto out ;
91
159
@@ -95,7 +163,8 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
95
163
cifs_sb -> local_nls , cifs_sb );
96
164
break ;
97
165
98
- case XATTR_CIFS_ACL : {
166
+ case XATTR_CIFS_ACL :
167
+ case XATTR_CIFS_NTSD : {
99
168
struct cifs_ntsd * pacl ;
100
169
101
170
if (!value )
@@ -106,12 +175,25 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
106
175
} else {
107
176
memcpy (pacl , value , size );
108
177
if (value &&
109
- pTcon -> ses -> server -> ops -> set_acl )
110
- rc = pTcon -> ses -> server -> ops -> set_acl (pacl ,
111
- size , inode ,
112
- full_path , CIFS_ACL_DACL );
113
- else
178
+ pTcon -> ses -> server -> ops -> set_acl ) {
179
+ rc = 0 ;
180
+ if (handler -> flags == XATTR_CIFS_NTSD ) {
181
+ /* set owner and DACL */
182
+ rc = pTcon -> ses -> server -> ops -> set_acl (
183
+ pacl , size , inode ,
184
+ full_path ,
185
+ CIFS_ACL_OWNER );
186
+ }
187
+ if (rc == 0 ) {
188
+ /* set DACL */
189
+ rc = pTcon -> ses -> server -> ops -> set_acl (
190
+ pacl , size , inode ,
191
+ full_path ,
192
+ CIFS_ACL_DACL );
193
+ }
194
+ } else {
114
195
rc = - EOPNOTSUPP ;
196
+ }
115
197
if (rc == 0 ) /* force revalidate of the inode */
116
198
CIFS_I (inode )-> time = 0 ;
117
199
kfree (pacl );
@@ -179,7 +261,7 @@ static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
179
261
void * value , size_t size )
180
262
{
181
263
ssize_t rc ;
182
- __u64 * pcreatetime ;
264
+ __u64 * pcreatetime ;
183
265
184
266
rc = cifs_revalidate_dentry_attr (dentry );
185
267
if (rc )
@@ -244,7 +326,9 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
244
326
full_path , name , value , size , cifs_sb );
245
327
break ;
246
328
247
- case XATTR_CIFS_ACL : {
329
+ case XATTR_CIFS_ACL :
330
+ case XATTR_CIFS_NTSD : {
331
+ /* the whole ntsd is fetched regardless */
248
332
u32 acllen ;
249
333
struct cifs_ntsd * pacl ;
250
334
@@ -382,6 +466,26 @@ static const struct xattr_handler smb3_acl_xattr_handler = {
382
466
.set = cifs_xattr_set ,
383
467
};
384
468
469
+ static const struct xattr_handler cifs_cifs_ntsd_xattr_handler = {
470
+ .name = CIFS_XATTR_CIFS_NTSD ,
471
+ .flags = XATTR_CIFS_NTSD ,
472
+ .get = cifs_xattr_get ,
473
+ .set = cifs_xattr_set ,
474
+ };
475
+
476
+ /*
477
+ * Although this is just an alias for the above, need to move away from
478
+ * confusing users and using the 20 year old term 'cifs' when it is no
479
+ * longer secure and was replaced by SMB2/SMB3 a long time ago, and
480
+ * SMB3 and later are highly secure.
481
+ */
482
+ static const struct xattr_handler smb3_ntsd_xattr_handler = {
483
+ .name = SMB3_XATTR_CIFS_NTSD ,
484
+ .flags = XATTR_CIFS_NTSD ,
485
+ .get = cifs_xattr_get ,
486
+ .set = cifs_xattr_set ,
487
+ };
488
+
385
489
static const struct xattr_handler cifs_posix_acl_access_xattr_handler = {
386
490
.name = XATTR_NAME_POSIX_ACL_ACCESS ,
387
491
.flags = XATTR_ACL_ACCESS ,
@@ -401,6 +505,8 @@ const struct xattr_handler *cifs_xattr_handlers[] = {
401
505
& cifs_os2_xattr_handler ,
402
506
& cifs_cifs_acl_xattr_handler ,
403
507
& smb3_acl_xattr_handler , /* alias for above since avoiding "cifs" */
508
+ & cifs_cifs_ntsd_xattr_handler ,
509
+ & smb3_ntsd_xattr_handler , /* alias for above since avoiding "cifs" */
404
510
& cifs_posix_acl_access_xattr_handler ,
405
511
& cifs_posix_acl_default_xattr_handler ,
406
512
NULL
0 commit comments