.. | .. |
---|
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 | /* |
---|
.. | .. |
---|
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 | 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 | 163 | cifs_sb->local_nls, cifs_sb); |
---|
96 | 164 | break; |
---|
97 | 165 | |
---|
98 | | - case XATTR_CIFS_ACL: { |
---|
99 | | -#ifdef CONFIG_CIFS_ACL |
---|
| 166 | + case XATTR_CIFS_ACL: |
---|
| 167 | + case XATTR_CIFS_NTSD: { |
---|
100 | 168 | struct cifs_ntsd *pacl; |
---|
101 | 169 | |
---|
102 | 170 | if (!value) |
---|
.. | .. |
---|
107 | 175 | } else { |
---|
108 | 176 | memcpy(pacl, value, size); |
---|
109 | 177 | if (value && |
---|
110 | | - pTcon->ses->server->ops->set_acl) |
---|
111 | | - rc = pTcon->ses->server->ops->set_acl(pacl, |
---|
112 | | - size, inode, |
---|
113 | | - full_path, CIFS_ACL_DACL); |
---|
114 | | - 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 { |
---|
115 | 195 | rc = -EOPNOTSUPP; |
---|
| 196 | + } |
---|
116 | 197 | if (rc == 0) /* force revalidate of the inode */ |
---|
117 | 198 | CIFS_I(inode)->time = 0; |
---|
118 | 199 | kfree(pacl); |
---|
119 | 200 | } |
---|
120 | | -#endif /* CONFIG_CIFS_ACL */ |
---|
121 | 201 | break; |
---|
122 | 202 | } |
---|
123 | 203 | |
---|
.. | .. |
---|
181 | 261 | void *value, size_t size) |
---|
182 | 262 | { |
---|
183 | 263 | ssize_t rc; |
---|
184 | | - __u64 * pcreatetime; |
---|
| 264 | + __u64 *pcreatetime; |
---|
185 | 265 | |
---|
186 | 266 | rc = cifs_revalidate_dentry_attr(dentry); |
---|
187 | 267 | if (rc) |
---|
.. | .. |
---|
201 | 281 | |
---|
202 | 282 | static int cifs_xattr_get(const struct xattr_handler *handler, |
---|
203 | 283 | struct dentry *dentry, struct inode *inode, |
---|
204 | | - const char *name, void *value, size_t size) |
---|
| 284 | + const char *name, void *value, size_t size, int flags) |
---|
205 | 285 | { |
---|
206 | 286 | ssize_t rc = -EOPNOTSUPP; |
---|
207 | 287 | unsigned int xid; |
---|
.. | .. |
---|
246 | 326 | full_path, name, value, size, cifs_sb); |
---|
247 | 327 | break; |
---|
248 | 328 | |
---|
249 | | - case XATTR_CIFS_ACL: { |
---|
250 | | -#ifdef CONFIG_CIFS_ACL |
---|
| 329 | + case XATTR_CIFS_ACL: |
---|
| 330 | + case XATTR_CIFS_NTSD: { |
---|
| 331 | + /* the whole ntsd is fetched regardless */ |
---|
251 | 332 | u32 acllen; |
---|
252 | 333 | struct cifs_ntsd *pacl; |
---|
253 | 334 | |
---|
.. | .. |
---|
270 | 351 | rc = acllen; |
---|
271 | 352 | kfree(pacl); |
---|
272 | 353 | } |
---|
273 | | -#endif /* CONFIG_CIFS_ACL */ |
---|
274 | 354 | break; |
---|
275 | 355 | } |
---|
276 | 356 | |
---|
.. | .. |
---|
386 | 466 | .set = cifs_xattr_set, |
---|
387 | 467 | }; |
---|
388 | 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 | + |
---|
389 | 489 | static const struct xattr_handler cifs_posix_acl_access_xattr_handler = { |
---|
390 | 490 | .name = XATTR_NAME_POSIX_ACL_ACCESS, |
---|
391 | 491 | .flags = XATTR_ACL_ACCESS, |
---|
.. | .. |
---|
405 | 505 | &cifs_os2_xattr_handler, |
---|
406 | 506 | &cifs_cifs_acl_xattr_handler, |
---|
407 | 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" */ |
---|
408 | 510 | &cifs_posix_acl_access_xattr_handler, |
---|
409 | 511 | &cifs_posix_acl_default_xattr_handler, |
---|
410 | 512 | NULL |
---|