3232#include "cifs_unicode.h"
3333
3434#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 */
3637#define CIFS_XATTR_ATTRIB "cifs.dosattrib" /* full name: user.cifs.dosattrib */
3738#define CIFS_XATTR_CREATETIME "cifs.creationtime" /* user.cifs.creationtime */
3839/*
3940 * Although these three are just aliases for the above, need to move away from
4041 * confusing users and using the 20+ year old term 'cifs' when it is no longer
4142 * secure, replaced by SMB2 (then even more highly secure SMB3) many years ago
4243 */
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 */
4446#define SMB3_XATTR_ATTRIB "smb3.dosattrib" /* full name: user.smb3.dosattrib */
4547#define SMB3_XATTR_CREATETIME "smb3.creationtime" /* user.smb3.creationtime */
4648/* BB need to add server (Samba e.g) support for security and trusted prefix */
4749
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+ }
49100
50101static int cifs_xattr_set (const struct xattr_handler * handler ,
51102 struct dentry * dentry , struct inode * inode ,
@@ -86,6 +137,23 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
86137
87138 switch (handler -> flags ) {
88139 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+
89157 if (cifs_sb -> mnt_cifs_flags & CIFS_MOUNT_NO_XATTR )
90158 goto out ;
91159
@@ -95,7 +163,8 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
95163 cifs_sb -> local_nls , cifs_sb );
96164 break ;
97165
98- case XATTR_CIFS_ACL : {
166+ case XATTR_CIFS_ACL :
167+ case XATTR_CIFS_NTSD : {
99168 struct cifs_ntsd * pacl ;
100169
101170 if (!value )
@@ -106,12 +175,25 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
106175 } else {
107176 memcpy (pacl , value , size );
108177 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 {
114195 rc = - EOPNOTSUPP ;
196+ }
115197 if (rc == 0 ) /* force revalidate of the inode */
116198 CIFS_I (inode )-> time = 0 ;
117199 kfree (pacl );
@@ -179,7 +261,7 @@ static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
179261 void * value , size_t size )
180262{
181263 ssize_t rc ;
182- __u64 * pcreatetime ;
264+ __u64 * pcreatetime ;
183265
184266 rc = cifs_revalidate_dentry_attr (dentry );
185267 if (rc )
@@ -244,7 +326,9 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
244326 full_path , name , value , size , cifs_sb );
245327 break ;
246328
247- case XATTR_CIFS_ACL : {
329+ case XATTR_CIFS_ACL :
330+ case XATTR_CIFS_NTSD : {
331+ /* the whole ntsd is fetched regardless */
248332 u32 acllen ;
249333 struct cifs_ntsd * pacl ;
250334
@@ -382,6 +466,26 @@ static const struct xattr_handler smb3_acl_xattr_handler = {
382466 .set = cifs_xattr_set ,
383467};
384468
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+
385489static const struct xattr_handler cifs_posix_acl_access_xattr_handler = {
386490 .name = XATTR_NAME_POSIX_ACL_ACCESS ,
387491 .flags = XATTR_ACL_ACCESS ,
@@ -401,6 +505,8 @@ const struct xattr_handler *cifs_xattr_handlers[] = {
401505 & cifs_os2_xattr_handler ,
402506 & cifs_cifs_acl_xattr_handler ,
403507 & 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" */
404510 & cifs_posix_acl_access_xattr_handler ,
405511 & cifs_posix_acl_default_xattr_handler ,
406512 NULL
0 commit comments