xref: /linux/fs/smb/client/xattr.c (revision 8a848efd482be65d488e888f96812d8729ea64ea)
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 
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 
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 
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->mnt_cifs_flags & 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 
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 
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 
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->mnt_cifs_flags & 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 
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->mnt_cifs_flags & 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