1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3 *
4 * Copyright (c) International Business Machines Corp., 2003, 2007
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 */
8
9 #include <linux/fs.h>
10 #include <linux/posix_acl_xattr.h>
11 #include <linux/slab.h>
12 #include <linux/xattr.h>
13 #include "cifsfs.h"
14 #include "cifsglob.h"
15 #include "cifsproto.h"
16 #include "cifs_debug.h"
17 #include "cifs_fs_sb.h"
18 #include "cifs_unicode.h"
19 #include "cifs_ioctl.h"
20
21 #define MAX_EA_VALUE_SIZE CIFSMaxBufSize
22 #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" /* DACL only */
23 #define CIFS_XATTR_CIFS_NTSD "system.cifs_ntsd" /* owner plus DACL */
24 #define CIFS_XATTR_CIFS_NTSD_FULL "system.cifs_ntsd_full" /* owner/DACL/SACL */
25 #define CIFS_XATTR_ATTRIB "cifs.dosattrib" /* full name: user.cifs.dosattrib */
26 #define CIFS_XATTR_CREATETIME "cifs.creationtime" /* user.cifs.creationtime */
27 /*
28 * Although these three are just aliases for the above, need to move away from
29 * confusing users and using the 20+ year old term 'cifs' when it is no longer
30 * secure, replaced by SMB2 (then even more highly secure SMB3) many years ago
31 */
32 #define SMB3_XATTR_CIFS_ACL "system.smb3_acl" /* DACL only */
33 #define SMB3_XATTR_CIFS_NTSD_SACL "system.smb3_ntsd_sacl" /* SACL only */
34 #define SMB3_XATTR_CIFS_NTSD_OWNER "system.smb3_ntsd_owner" /* owner only */
35 #define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd" /* owner plus DACL */
36 #define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full" /* owner/DACL/SACL */
37 #define SMB3_XATTR_ATTRIB "smb3.dosattrib" /* full name: user.smb3.dosattrib */
38 #define SMB3_XATTR_CREATETIME "smb3.creationtime" /* user.smb3.creationtime */
39 /* BB need to add server (Samba e.g) support for security and trusted prefix */
40
41 enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
42 XATTR_CIFS_NTSD_SACL, XATTR_CIFS_NTSD_OWNER,
43 XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL };
44
cifs_attrib_set(unsigned int xid,struct cifs_tcon * pTcon,struct inode * inode,const char * full_path,const void * value,size_t size)45 static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon,
46 struct inode *inode, const char *full_path,
47 const void *value, size_t size)
48 {
49 ssize_t rc = -EOPNOTSUPP;
50 __u32 *pattrib = (__u32 *)value;
51 __u32 attrib;
52 FILE_BASIC_INFO info_buf;
53
54 if ((value == NULL) || (size != sizeof(__u32)))
55 return -ERANGE;
56
57 memset(&info_buf, 0, sizeof(info_buf));
58 attrib = *pattrib;
59 info_buf.Attributes = cpu_to_le32(attrib);
60 if (pTcon->ses->server->ops->set_file_info)
61 rc = pTcon->ses->server->ops->set_file_info(inode, full_path,
62 &info_buf, xid);
63 if (rc == 0)
64 CIFS_I(inode)->cifsAttrs = attrib;
65
66 return rc;
67 }
68
cifs_creation_time_set(unsigned int xid,struct cifs_tcon * pTcon,struct inode * inode,const char * full_path,const void * value,size_t size)69 static int cifs_creation_time_set(unsigned int xid, struct cifs_tcon *pTcon,
70 struct inode *inode, const char *full_path,
71 const void *value, size_t size)
72 {
73 ssize_t rc = -EOPNOTSUPP;
74 __u64 *pcreation_time = (__u64 *)value;
75 __u64 creation_time;
76 FILE_BASIC_INFO info_buf;
77
78 if ((value == NULL) || (size != sizeof(__u64)))
79 return -ERANGE;
80
81 memset(&info_buf, 0, sizeof(info_buf));
82 creation_time = *pcreation_time;
83 info_buf.CreationTime = cpu_to_le64(creation_time);
84 if (pTcon->ses->server->ops->set_file_info)
85 rc = pTcon->ses->server->ops->set_file_info(inode, full_path,
86 &info_buf, xid);
87 if (rc == 0)
88 CIFS_I(inode)->createtime = creation_time;
89
90 return rc;
91 }
92
cifs_xattr_set(const struct xattr_handler * handler,struct mnt_idmap * idmap,struct dentry * dentry,struct inode * inode,const char * name,const void * value,size_t size,int flags)93 static int cifs_xattr_set(const struct xattr_handler *handler,
94 struct mnt_idmap *idmap,
95 struct dentry *dentry, struct inode *inode,
96 const char *name, const void *value,
97 size_t size, int flags)
98 {
99 int rc = -EOPNOTSUPP;
100 unsigned int xid;
101 struct super_block *sb = dentry->d_sb;
102 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
103 struct tcon_link *tlink;
104 struct cifs_tcon *pTcon;
105 const char *full_path;
106 void *page;
107
108 tlink = cifs_sb_tlink(cifs_sb);
109 if (IS_ERR(tlink))
110 return PTR_ERR(tlink);
111 pTcon = tlink_tcon(tlink);
112
113 xid = get_xid();
114 page = alloc_dentry_path();
115
116 full_path = build_path_from_dentry(dentry, page);
117 if (IS_ERR(full_path)) {
118 rc = PTR_ERR(full_path);
119 goto out;
120 }
121 /* return dos attributes as pseudo xattr */
122 /* return alt name if available as pseudo attr */
123
124 /* if proc/fs/cifs/streamstoxattr is set then
125 search server for EAs or streams to
126 returns as xattrs */
127 if (size > MAX_EA_VALUE_SIZE) {
128 cifs_dbg(FYI, "size of EA value too large\n");
129 rc = -EOPNOTSUPP;
130 goto out;
131 }
132
133 switch (handler->flags) {
134 case XATTR_USER:
135 cifs_dbg(FYI, "%s:setting user xattr %s\n", __func__, name);
136 if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
137 (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
138 rc = cifs_attrib_set(xid, pTcon, inode, full_path,
139 value, size);
140 if (rc == 0) /* force revalidate of the inode */
141 CIFS_I(inode)->time = 0;
142 break;
143 } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
144 (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
145 rc = cifs_creation_time_set(xid, pTcon, inode,
146 full_path, value, size);
147 if (rc == 0) /* force revalidate of the inode */
148 CIFS_I(inode)->time = 0;
149 break;
150 }
151
152 if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
153 goto out;
154
155 if (pTcon->ses->server->ops->set_EA) {
156 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
157 full_path, name, value, (__u16)size,
158 cifs_sb->local_nls, cifs_sb);
159 if (rc == 0)
160 inode_set_ctime_current(inode);
161 }
162 break;
163
164 case XATTR_CIFS_ACL:
165 case XATTR_CIFS_NTSD_SACL:
166 case XATTR_CIFS_NTSD_OWNER:
167 case XATTR_CIFS_NTSD:
168 case XATTR_CIFS_NTSD_FULL: {
169 struct smb_ntsd *pacl;
170
171 if (!value)
172 goto out;
173 pacl = kmalloc(size, GFP_KERNEL);
174 if (!pacl) {
175 rc = -ENOMEM;
176 } else {
177 memcpy(pacl, value, size);
178 if (pTcon->ses->server->ops->set_acl) {
179 int aclflags = 0;
180
181 switch (handler->flags) {
182 case XATTR_CIFS_NTSD_FULL:
183 aclflags = (CIFS_ACL_OWNER |
184 CIFS_ACL_GROUP |
185 CIFS_ACL_DACL |
186 CIFS_ACL_SACL);
187 break;
188 case XATTR_CIFS_NTSD:
189 aclflags = (CIFS_ACL_OWNER |
190 CIFS_ACL_GROUP |
191 CIFS_ACL_DACL);
192 break;
193 case XATTR_CIFS_NTSD_OWNER:
194 aclflags = (CIFS_ACL_OWNER |
195 CIFS_ACL_GROUP);
196 break;
197 case XATTR_CIFS_NTSD_SACL:
198 aclflags = CIFS_ACL_SACL;
199 break;
200 case XATTR_CIFS_ACL:
201 default:
202 aclflags = CIFS_ACL_DACL;
203 }
204
205 rc = pTcon->ses->server->ops->set_acl(pacl,
206 size, inode, full_path, aclflags);
207 } else {
208 rc = -EOPNOTSUPP;
209 }
210 if (rc == 0) /* force revalidate of the inode */
211 CIFS_I(inode)->time = 0;
212 kfree(pacl);
213 }
214 break;
215 }
216 }
217
218 out:
219 free_dentry_path(page);
220 free_xid(xid);
221 cifs_put_tlink(tlink);
222 return rc;
223 }
224
cifs_attrib_get(struct dentry * dentry,struct inode * inode,void * value,size_t size)225 static int cifs_attrib_get(struct dentry *dentry,
226 struct inode *inode, void *value,
227 size_t size)
228 {
229 ssize_t rc;
230 __u32 *pattribute;
231
232 rc = cifs_revalidate_dentry_attr(dentry);
233
234 if (rc)
235 return rc;
236
237 if ((value == NULL) || (size == 0))
238 return sizeof(__u32);
239 else if (size < sizeof(__u32))
240 return -ERANGE;
241
242 /* return dos attributes as pseudo xattr */
243 pattribute = (__u32 *)value;
244 *pattribute = CIFS_I(inode)->cifsAttrs;
245
246 return sizeof(__u32);
247 }
248
cifs_creation_time_get(struct dentry * dentry,struct inode * inode,void * value,size_t size)249 static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
250 void *value, size_t size)
251 {
252 ssize_t rc;
253 __u64 *pcreatetime;
254
255 rc = cifs_revalidate_dentry_attr(dentry);
256 if (rc)
257 return rc;
258
259 if ((value == NULL) || (size == 0))
260 return sizeof(__u64);
261 else if (size < sizeof(__u64))
262 return -ERANGE;
263
264 /* return dos attributes as pseudo xattr */
265 pcreatetime = (__u64 *)value;
266 *pcreatetime = CIFS_I(inode)->createtime;
267 return sizeof(__u64);
268 }
269
270
cifs_xattr_get(const struct xattr_handler * handler,struct dentry * dentry,struct inode * inode,const char * name,void * value,size_t size)271 static int cifs_xattr_get(const struct xattr_handler *handler,
272 struct dentry *dentry, struct inode *inode,
273 const char *name, void *value, size_t size)
274 {
275 ssize_t rc = -EOPNOTSUPP;
276 unsigned int xid;
277 struct super_block *sb = dentry->d_sb;
278 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
279 struct tcon_link *tlink;
280 struct cifs_tcon *pTcon;
281 const char *full_path;
282 void *page;
283
284 tlink = cifs_sb_tlink(cifs_sb);
285 if (IS_ERR(tlink))
286 return PTR_ERR(tlink);
287 pTcon = tlink_tcon(tlink);
288
289 xid = get_xid();
290 page = alloc_dentry_path();
291
292 full_path = build_path_from_dentry(dentry, page);
293 if (IS_ERR(full_path)) {
294 rc = PTR_ERR(full_path);
295 goto out;
296 }
297
298 /* return alt name if available as pseudo attr */
299 switch (handler->flags) {
300 case XATTR_USER:
301 cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name);
302 if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
303 (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
304 rc = cifs_attrib_get(dentry, inode, value, size);
305 break;
306 } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
307 (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
308 rc = cifs_creation_time_get(dentry, inode, value, size);
309 break;
310 }
311
312 if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
313 goto out;
314
315 if (pTcon->ses->server->ops->query_all_EAs)
316 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
317 full_path, name, value, size, cifs_sb);
318 break;
319
320 case XATTR_CIFS_ACL:
321 case XATTR_CIFS_NTSD_SACL:
322 case XATTR_CIFS_NTSD_OWNER:
323 case XATTR_CIFS_NTSD:
324 case XATTR_CIFS_NTSD_FULL: {
325 /*
326 * fetch owner, DACL, and SACL if asked for full descriptor,
327 * fetch owner and DACL otherwise
328 */
329 u32 acllen, extra_info;
330 struct smb_ntsd *pacl;
331
332 if (pTcon->ses->server->ops->get_acl == NULL)
333 goto out; /* rc already EOPNOTSUPP */
334
335 switch (handler->flags) {
336 case XATTR_CIFS_NTSD_FULL:
337 extra_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO | SACL_SECINFO;
338 break;
339 case XATTR_CIFS_NTSD:
340 extra_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO;
341 break;
342 case XATTR_CIFS_NTSD_OWNER:
343 extra_info = OWNER_SECINFO | GROUP_SECINFO;
344 break;
345 case XATTR_CIFS_NTSD_SACL:
346 extra_info = SACL_SECINFO;
347 break;
348 case XATTR_CIFS_ACL:
349 default:
350 extra_info = DACL_SECINFO;
351 break;
352 }
353 pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
354 inode, full_path, &acllen, extra_info);
355 if (IS_ERR(pacl)) {
356 rc = PTR_ERR(pacl);
357 cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
358 __func__, rc);
359 } else {
360 if (value) {
361 if (acllen > size)
362 acllen = -ERANGE;
363 else
364 memcpy(value, pacl, acllen);
365 }
366 rc = acllen;
367 kfree(pacl);
368 }
369 break;
370 }
371 }
372
373 /* We could add an additional check for streams ie
374 if proc/fs/cifs/streamstoxattr is set then
375 search server for EAs or streams to
376 returns as xattrs */
377
378 if (rc == -EINVAL)
379 rc = -EOPNOTSUPP;
380
381 out:
382 free_dentry_path(page);
383 free_xid(xid);
384 cifs_put_tlink(tlink);
385 return rc;
386 }
387
cifs_listxattr(struct dentry * direntry,char * data,size_t buf_size)388 ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
389 {
390 ssize_t rc = -EOPNOTSUPP;
391 unsigned int xid;
392 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
393 struct tcon_link *tlink;
394 struct cifs_tcon *pTcon;
395 const char *full_path;
396 void *page;
397
398 if (unlikely(cifs_forced_shutdown(cifs_sb)))
399 return smb_EIO(smb_eio_trace_forced_shutdown);
400
401 if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
402 return -EOPNOTSUPP;
403
404 tlink = cifs_sb_tlink(cifs_sb);
405 if (IS_ERR(tlink))
406 return PTR_ERR(tlink);
407 pTcon = tlink_tcon(tlink);
408
409 xid = get_xid();
410 page = alloc_dentry_path();
411
412 full_path = build_path_from_dentry(direntry, page);
413 if (IS_ERR(full_path)) {
414 rc = PTR_ERR(full_path);
415 goto list_ea_exit;
416 }
417 /* return dos attributes as pseudo xattr */
418 /* return alt name if available as pseudo attr */
419
420 /* if proc/fs/cifs/streamstoxattr is set then
421 search server for EAs or streams to
422 returns as xattrs */
423
424 if (pTcon->ses->server->ops->query_all_EAs)
425 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
426 full_path, NULL, data, buf_size, cifs_sb);
427 list_ea_exit:
428 free_dentry_path(page);
429 free_xid(xid);
430 cifs_put_tlink(tlink);
431 return rc;
432 }
433
434 static const struct xattr_handler cifs_user_xattr_handler = {
435 .prefix = XATTR_USER_PREFIX,
436 .flags = XATTR_USER,
437 .get = cifs_xattr_get,
438 .set = cifs_xattr_set,
439 };
440
441 /* os2.* attributes are treated like user.* attributes */
442 static const struct xattr_handler cifs_os2_xattr_handler = {
443 .prefix = XATTR_OS2_PREFIX,
444 .flags = XATTR_USER,
445 .get = cifs_xattr_get,
446 .set = cifs_xattr_set,
447 };
448
449 static const struct xattr_handler cifs_cifs_acl_xattr_handler = {
450 .name = CIFS_XATTR_CIFS_ACL,
451 .flags = XATTR_CIFS_ACL,
452 .get = cifs_xattr_get,
453 .set = cifs_xattr_set,
454 };
455
456 /*
457 * Although this is just an alias for the above, need to move away from
458 * confusing users and using the 20 year old term 'cifs' when it is no
459 * longer secure and was replaced by SMB2/SMB3 a long time ago, and
460 * SMB3 and later are highly secure.
461 */
462 static const struct xattr_handler smb3_acl_xattr_handler = {
463 .name = SMB3_XATTR_CIFS_ACL,
464 .flags = XATTR_CIFS_ACL,
465 .get = cifs_xattr_get,
466 .set = cifs_xattr_set,
467 };
468
469 static const struct xattr_handler smb3_ntsd_sacl_xattr_handler = {
470 .name = SMB3_XATTR_CIFS_NTSD_SACL,
471 .flags = XATTR_CIFS_NTSD_SACL,
472 .get = cifs_xattr_get,
473 .set = cifs_xattr_set,
474 };
475
476 static const struct xattr_handler smb3_ntsd_owner_xattr_handler = {
477 .name = SMB3_XATTR_CIFS_NTSD_OWNER,
478 .flags = XATTR_CIFS_NTSD_OWNER,
479 .get = cifs_xattr_get,
480 .set = cifs_xattr_set,
481 };
482
483 static const struct xattr_handler cifs_cifs_ntsd_xattr_handler = {
484 .name = CIFS_XATTR_CIFS_NTSD,
485 .flags = XATTR_CIFS_NTSD,
486 .get = cifs_xattr_get,
487 .set = cifs_xattr_set,
488 };
489
490 /*
491 * Although this is just an alias for the above, need to move away from
492 * confusing users and using the 20 year old term 'cifs' when it is no
493 * longer secure and was replaced by SMB2/SMB3 a long time ago, and
494 * SMB3 and later are highly secure.
495 */
496 static const struct xattr_handler smb3_ntsd_xattr_handler = {
497 .name = SMB3_XATTR_CIFS_NTSD,
498 .flags = XATTR_CIFS_NTSD,
499 .get = cifs_xattr_get,
500 .set = cifs_xattr_set,
501 };
502
503 static const struct xattr_handler cifs_cifs_ntsd_full_xattr_handler = {
504 .name = CIFS_XATTR_CIFS_NTSD_FULL,
505 .flags = XATTR_CIFS_NTSD_FULL,
506 .get = cifs_xattr_get,
507 .set = cifs_xattr_set,
508 };
509
510 /*
511 * Although this is just an alias for the above, need to move away from
512 * confusing users and using the 20 year old term 'cifs' when it is no
513 * longer secure and was replaced by SMB2/SMB3 a long time ago, and
514 * SMB3 and later are highly secure.
515 */
516 static const struct xattr_handler smb3_ntsd_full_xattr_handler = {
517 .name = SMB3_XATTR_CIFS_NTSD_FULL,
518 .flags = XATTR_CIFS_NTSD_FULL,
519 .get = cifs_xattr_get,
520 .set = cifs_xattr_set,
521 };
522
523 const struct xattr_handler * const cifs_xattr_handlers[] = {
524 &cifs_user_xattr_handler,
525 &cifs_os2_xattr_handler,
526 &cifs_cifs_acl_xattr_handler,
527 &smb3_acl_xattr_handler, /* alias for above since avoiding "cifs" */
528 &smb3_ntsd_sacl_xattr_handler,
529 &smb3_ntsd_owner_xattr_handler,
530 &cifs_cifs_ntsd_xattr_handler,
531 &smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */
532 &cifs_cifs_ntsd_full_xattr_handler,
533 &smb3_ntsd_full_xattr_handler, /* alias for above since avoiding "cifs" */
534 NULL
535 };
536