FreeBSD kernel kern code
vfs_extattr.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 1999-2001 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * This software was developed by Robert Watson for the TrustedBSD Project.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$BSDSUniX$");
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/capability.h>
35 #include <sys/lock.h>
36 #include <sys/mount.h>
37 #include <sys/mutex.h>
38 #include <sys/sysproto.h>
39 #include <sys/fcntl.h>
40 #include <sys/namei.h>
41 #include <sys/filedesc.h>
42 #include <sys/limits.h>
43 #include <sys/vnode.h>
44 #include <sys/proc.h>
45 #include <sys/extattr.h>
46 
47 #include <security/audit/audit.h>
48 #include <security/mac/mac_framework.h>
49 
50 /*
51  * Syscall to push extended attribute configuration information into the VFS.
52  * Accepts a path, which it converts to a mountpoint, as well as a command
53  * (int cmd), and attribute name and misc data.
54  *
55  * Currently this is used only by UFS1 extended attributes.
56  */
57 int
59  struct thread *td;
60  struct extattrctl_args /* {
61  const char *path;
62  int cmd;
63  const char *filename;
64  int attrnamespace;
65  const char *attrname;
66  } */ *uap;
67 {
68  struct vnode *filename_vp;
69  struct nameidata nd;
70  struct mount *mp, *mp_writable;
71  char attrname[EXTATTR_MAXNAMELEN];
72  int vfslocked, fnvfslocked, error;
73 
74  AUDIT_ARG_CMD(uap->cmd);
75  AUDIT_ARG_VALUE(uap->attrnamespace);
76  /*
77  * uap->attrname is not always defined. We check again later when we
78  * invoke the VFS call so as to pass in NULL there if needed.
79  */
80  if (uap->attrname != NULL) {
81  error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
82  NULL);
83  if (error)
84  return (error);
85  }
86  AUDIT_ARG_TEXT(attrname);
87 
88  vfslocked = fnvfslocked = 0;
89  mp = NULL;
90  filename_vp = NULL;
91  if (uap->filename != NULL) {
92  NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE2,
93  UIO_USERSPACE, uap->filename, td);
94  error = namei(&nd);
95  if (error)
96  return (error);
97  fnvfslocked = NDHASGIANT(&nd);
98  filename_vp = nd.ni_vp;
99  NDFREE(&nd, NDF_NO_VP_RELE);
100  }
101 
102  /* uap->path is always defined. */
103  NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF | AUDITVNODE1,
104  UIO_USERSPACE, uap->path, td);
105  error = namei(&nd);
106  if (error)
107  goto out;
108  vfslocked = NDHASGIANT(&nd);
109  mp = nd.ni_vp->v_mount;
110  error = vfs_busy(mp, 0);
111  if (error) {
112  NDFREE(&nd, 0);
113  mp = NULL;
114  goto out;
115  }
116  VOP_UNLOCK(nd.ni_vp, 0);
117  error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
118  NDFREE(&nd, NDF_NO_VP_UNLOCK);
119  if (error)
120  goto out;
121  if (filename_vp != NULL) {
122  /*
123  * uap->filename is not always defined. If it is,
124  * grab a vnode lock, which VFS_EXTATTRCTL() will
125  * later release.
126  */
127  error = vn_lock(filename_vp, LK_EXCLUSIVE);
128  if (error) {
129  vn_finished_write(mp_writable);
130  goto out;
131  }
132  }
133 
134  error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
135  uap->attrname != NULL ? attrname : NULL);
136 
137  vn_finished_write(mp_writable);
138 out:
139  if (mp != NULL)
140  vfs_unbusy(mp);
141 
142  /*
143  * VFS_EXTATTRCTL will have unlocked, but not de-ref'd, filename_vp,
144  * so vrele it if it is defined.
145  */
146  if (filename_vp != NULL)
147  vrele(filename_vp);
148  VFS_UNLOCK_GIANT(fnvfslocked);
149  VFS_UNLOCK_GIANT(vfslocked);
150  return (error);
151 }
152 
153 /*-
154  * Set a named extended attribute on a file or directory
155  *
156  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
157  * kernelspace string pointer "attrname", userspace buffer
158  * pointer "data", buffer length "nbytes", thread "td".
159  * Returns: 0 on success, an error number otherwise
160  * Locks: none
161  * References: vp must be a valid reference for the duration of the call
162  */
163 static int
164 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
165  void *data, size_t nbytes, struct thread *td)
166 {
167  struct mount *mp;
168  struct uio auio;
169  struct iovec aiov;
170  ssize_t cnt;
171  int error;
172 
173  VFS_ASSERT_GIANT(vp->v_mount);
174  error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
175  if (error)
176  return (error);
177  vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
178 
179  aiov.iov_base = data;
180  aiov.iov_len = nbytes;
181  auio.uio_iov = &aiov;
182  auio.uio_iovcnt = 1;
183  auio.uio_offset = 0;
184  if (nbytes > IOSIZE_MAX) {
185  error = EINVAL;
186  goto done;
187  }
188  auio.uio_resid = nbytes;
189  auio.uio_rw = UIO_WRITE;
190  auio.uio_segflg = UIO_USERSPACE;
191  auio.uio_td = td;
192  cnt = nbytes;
193 
194 #ifdef MAC
195  error = mac_vnode_check_setextattr(td->td_ucred, vp, attrnamespace,
196  attrname);
197  if (error)
198  goto done;
199 #endif
200 
201  error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
202  td->td_ucred, td);
203  cnt -= auio.uio_resid;
204  td->td_retval[0] = cnt;
205 
206 done:
207  VOP_UNLOCK(vp, 0);
208  vn_finished_write(mp);
209  return (error);
210 }
211 
212 int
214  struct thread *td;
215  struct extattr_set_fd_args /* {
216  int fd;
217  int attrnamespace;
218  const char *attrname;
219  void *data;
220  size_t nbytes;
221  } */ *uap;
222 {
223  struct file *fp;
224  char attrname[EXTATTR_MAXNAMELEN];
225  int vfslocked, error;
226 
227  AUDIT_ARG_FD(uap->fd);
228  AUDIT_ARG_VALUE(uap->attrnamespace);
229  error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
230  if (error)
231  return (error);
232  AUDIT_ARG_TEXT(attrname);
233 
234  error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_SET, &fp);
235  if (error)
236  return (error);
237 
238  vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
239  error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
240  attrname, uap->data, uap->nbytes, td);
241  fdrop(fp, td);
242  VFS_UNLOCK_GIANT(vfslocked);
243 
244  return (error);
245 }
246 
247 int
249  struct thread *td;
250  struct extattr_set_file_args /* {
251  const char *path;
252  int attrnamespace;
253  const char *attrname;
254  void *data;
255  size_t nbytes;
256  } */ *uap;
257 {
258  struct nameidata nd;
259  char attrname[EXTATTR_MAXNAMELEN];
260  int vfslocked, error;
261 
262  AUDIT_ARG_VALUE(uap->attrnamespace);
263  error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
264  if (error)
265  return (error);
266  AUDIT_ARG_TEXT(attrname);
267 
268  NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
269  uap->path, td);
270  error = namei(&nd);
271  if (error)
272  return (error);
273  NDFREE(&nd, NDF_ONLY_PNBUF);
274 
275  vfslocked = NDHASGIANT(&nd);
276  error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
277  uap->data, uap->nbytes, td);
278 
279  vrele(nd.ni_vp);
280  VFS_UNLOCK_GIANT(vfslocked);
281  return (error);
282 }
283 
284 int
286  struct thread *td;
287  struct extattr_set_link_args /* {
288  const char *path;
289  int attrnamespace;
290  const char *attrname;
291  void *data;
292  size_t nbytes;
293  } */ *uap;
294 {
295  struct nameidata nd;
296  char attrname[EXTATTR_MAXNAMELEN];
297  int vfslocked, error;
298 
299  AUDIT_ARG_VALUE(uap->attrnamespace);
300  error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
301  if (error)
302  return (error);
303  AUDIT_ARG_TEXT(attrname);
304 
305  NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
306  uap->path, td);
307  error = namei(&nd);
308  if (error)
309  return (error);
310  NDFREE(&nd, NDF_ONLY_PNBUF);
311 
312  vfslocked = NDHASGIANT(&nd);
313  error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
314  uap->data, uap->nbytes, td);
315 
316  vrele(nd.ni_vp);
317  VFS_UNLOCK_GIANT(vfslocked);
318  return (error);
319 }
320 
321 /*-
322  * Get a named extended attribute on a file or directory
323  *
324  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
325  * kernelspace string pointer "attrname", userspace buffer
326  * pointer "data", buffer length "nbytes", thread "td".
327  * Returns: 0 on success, an error number otherwise
328  * Locks: none
329  * References: vp must be a valid reference for the duration of the call
330  */
331 static int
332 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
333  void *data, size_t nbytes, struct thread *td)
334 {
335  struct uio auio, *auiop;
336  struct iovec aiov;
337  ssize_t cnt;
338  size_t size, *sizep;
339  int error;
340 
341  VFS_ASSERT_GIANT(vp->v_mount);
342  vn_lock(vp, LK_SHARED | LK_RETRY);
343 
344  /*
345  * Slightly unusual semantics: if the user provides a NULL data
346  * pointer, they don't want to receive the data, just the maximum
347  * read length.
348  */
349  auiop = NULL;
350  sizep = NULL;
351  cnt = 0;
352  if (data != NULL) {
353  aiov.iov_base = data;
354  aiov.iov_len = nbytes;
355  auio.uio_iov = &aiov;
356  auio.uio_iovcnt = 1;
357  auio.uio_offset = 0;
358  if (nbytes > IOSIZE_MAX) {
359  error = EINVAL;
360  goto done;
361  }
362  auio.uio_resid = nbytes;
363  auio.uio_rw = UIO_READ;
364  auio.uio_segflg = UIO_USERSPACE;
365  auio.uio_td = td;
366  auiop = &auio;
367  cnt = nbytes;
368  } else
369  sizep = &size;
370 
371 #ifdef MAC
372  error = mac_vnode_check_getextattr(td->td_ucred, vp, attrnamespace,
373  attrname);
374  if (error)
375  goto done;
376 #endif
377 
378  error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
379  td->td_ucred, td);
380 
381  if (auiop != NULL) {
382  cnt -= auio.uio_resid;
383  td->td_retval[0] = cnt;
384  } else
385  td->td_retval[0] = size;
386 
387 done:
388  VOP_UNLOCK(vp, 0);
389  return (error);
390 }
391 
392 int
394  struct thread *td;
395  struct extattr_get_fd_args /* {
396  int fd;
397  int attrnamespace;
398  const char *attrname;
399  void *data;
400  size_t nbytes;
401  } */ *uap;
402 {
403  struct file *fp;
404  char attrname[EXTATTR_MAXNAMELEN];
405  int vfslocked, error;
406 
407  AUDIT_ARG_FD(uap->fd);
408  AUDIT_ARG_VALUE(uap->attrnamespace);
409  error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
410  if (error)
411  return (error);
412  AUDIT_ARG_TEXT(attrname);
413 
414  error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_GET, &fp);
415  if (error)
416  return (error);
417 
418  vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
419  error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
420  attrname, uap->data, uap->nbytes, td);
421 
422  fdrop(fp, td);
423  VFS_UNLOCK_GIANT(vfslocked);
424  return (error);
425 }
426 
427 int
429  struct thread *td;
430  struct extattr_get_file_args /* {
431  const char *path;
432  int attrnamespace;
433  const char *attrname;
434  void *data;
435  size_t nbytes;
436  } */ *uap;
437 {
438  struct nameidata nd;
439  char attrname[EXTATTR_MAXNAMELEN];
440  int vfslocked, error;
441 
442  AUDIT_ARG_VALUE(uap->attrnamespace);
443  error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
444  if (error)
445  return (error);
446  AUDIT_ARG_TEXT(attrname);
447 
448  NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
449  uap->path, td);
450  error = namei(&nd);
451  if (error)
452  return (error);
453  NDFREE(&nd, NDF_ONLY_PNBUF);
454 
455  vfslocked = NDHASGIANT(&nd);
456  error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
457  uap->data, uap->nbytes, td);
458 
459  vrele(nd.ni_vp);
460  VFS_UNLOCK_GIANT(vfslocked);
461  return (error);
462 }
463 
464 int
466  struct thread *td;
467  struct extattr_get_link_args /* {
468  const char *path;
469  int attrnamespace;
470  const char *attrname;
471  void *data;
472  size_t nbytes;
473  } */ *uap;
474 {
475  struct nameidata nd;
476  char attrname[EXTATTR_MAXNAMELEN];
477  int vfslocked, error;
478 
479  AUDIT_ARG_VALUE(uap->attrnamespace);
480  error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
481  if (error)
482  return (error);
483  AUDIT_ARG_TEXT(attrname);
484 
485  NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
486  uap->path, td);
487  error = namei(&nd);
488  if (error)
489  return (error);
490  NDFREE(&nd, NDF_ONLY_PNBUF);
491 
492  vfslocked = NDHASGIANT(&nd);
493  error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
494  uap->data, uap->nbytes, td);
495 
496  vrele(nd.ni_vp);
497  VFS_UNLOCK_GIANT(vfslocked);
498  return (error);
499 }
500 
501 /*
502  * extattr_delete_vp(): Delete a named extended attribute on a file or
503  * directory
504  *
505  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
506  * kernelspace string pointer "attrname", proc "p"
507  * Returns: 0 on success, an error number otherwise
508  * Locks: none
509  * References: vp must be a valid reference for the duration of the call
510  */
511 static int
512 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
513  struct thread *td)
514 {
515  struct mount *mp;
516  int error;
517 
518  VFS_ASSERT_GIANT(vp->v_mount);
519  error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
520  if (error)
521  return (error);
522  vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
523 
524 #ifdef MAC
525  error = mac_vnode_check_deleteextattr(td->td_ucred, vp, attrnamespace,
526  attrname);
527  if (error)
528  goto done;
529 #endif
530 
531  error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, td->td_ucred,
532  td);
533  if (error == EOPNOTSUPP)
534  error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
535  td->td_ucred, td);
536 #ifdef MAC
537 done:
538 #endif
539  VOP_UNLOCK(vp, 0);
540  vn_finished_write(mp);
541  return (error);
542 }
543 
544 int
546  struct thread *td;
547  struct extattr_delete_fd_args /* {
548  int fd;
549  int attrnamespace;
550  const char *attrname;
551  } */ *uap;
552 {
553  struct file *fp;
554  char attrname[EXTATTR_MAXNAMELEN];
555  int vfslocked, error;
556 
557  AUDIT_ARG_FD(uap->fd);
558  AUDIT_ARG_VALUE(uap->attrnamespace);
559  error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
560  if (error)
561  return (error);
562  AUDIT_ARG_TEXT(attrname);
563 
564  error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_DELETE,
565  &fp);
566  if (error)
567  return (error);
568 
569  vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
570  error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
571  attrname, td);
572  fdrop(fp, td);
573  VFS_UNLOCK_GIANT(vfslocked);
574  return (error);
575 }
576 
577 int
579  struct thread *td;
580  struct extattr_delete_file_args /* {
581  const char *path;
582  int attrnamespace;
583  const char *attrname;
584  } */ *uap;
585 {
586  struct nameidata nd;
587  char attrname[EXTATTR_MAXNAMELEN];
588  int vfslocked, error;
589 
590  AUDIT_ARG_VALUE(uap->attrnamespace);
591  error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
592  if (error)
593  return(error);
594  AUDIT_ARG_TEXT(attrname);
595 
596  NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
597  uap->path, td);
598  error = namei(&nd);
599  if (error)
600  return(error);
601  NDFREE(&nd, NDF_ONLY_PNBUF);
602 
603  vfslocked = NDHASGIANT(&nd);
604  error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
605  vrele(nd.ni_vp);
606  VFS_UNLOCK_GIANT(vfslocked);
607  return(error);
608 }
609 
610 int
612  struct thread *td;
613  struct extattr_delete_link_args /* {
614  const char *path;
615  int attrnamespace;
616  const char *attrname;
617  } */ *uap;
618 {
619  struct nameidata nd;
620  char attrname[EXTATTR_MAXNAMELEN];
621  int vfslocked, error;
622 
623  AUDIT_ARG_VALUE(uap->attrnamespace);
624  error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
625  if (error)
626  return(error);
627  AUDIT_ARG_TEXT(attrname);
628 
629  NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
630  uap->path, td);
631  error = namei(&nd);
632  if (error)
633  return(error);
634  NDFREE(&nd, NDF_ONLY_PNBUF);
635 
636  vfslocked = NDHASGIANT(&nd);
637  error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
638  vrele(nd.ni_vp);
639  VFS_UNLOCK_GIANT(vfslocked);
640  return(error);
641 }
642 
643 /*-
644  * Retrieve a list of extended attributes on a file or directory.
645  *
646  * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
647  * userspace buffer pointer "data", buffer length "nbytes",
648  * thread "td".
649  * Returns: 0 on success, an error number otherwise
650  * Locks: none
651  * References: vp must be a valid reference for the duration of the call
652  */
653 static int
654 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
655  size_t nbytes, struct thread *td)
656 {
657  struct uio auio, *auiop;
658  size_t size, *sizep;
659  struct iovec aiov;
660  ssize_t cnt;
661  int error;
662 
663  VFS_ASSERT_GIANT(vp->v_mount);
664  vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
665 
666  auiop = NULL;
667  sizep = NULL;
668  cnt = 0;
669  if (data != NULL) {
670  aiov.iov_base = data;
671  aiov.iov_len = nbytes;
672  auio.uio_iov = &aiov;
673  auio.uio_iovcnt = 1;
674  auio.uio_offset = 0;
675  if (nbytes > IOSIZE_MAX) {
676  error = EINVAL;
677  goto done;
678  }
679  auio.uio_resid = nbytes;
680  auio.uio_rw = UIO_READ;
681  auio.uio_segflg = UIO_USERSPACE;
682  auio.uio_td = td;
683  auiop = &auio;
684  cnt = nbytes;
685  } else
686  sizep = &size;
687 
688 #ifdef MAC
689  error = mac_vnode_check_listextattr(td->td_ucred, vp, attrnamespace);
690  if (error)
691  goto done;
692 #endif
693 
694  error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
695  td->td_ucred, td);
696 
697  if (auiop != NULL) {
698  cnt -= auio.uio_resid;
699  td->td_retval[0] = cnt;
700  } else
701  td->td_retval[0] = size;
702 
703 done:
704  VOP_UNLOCK(vp, 0);
705  return (error);
706 }
707 
708 
709 int
711  struct thread *td;
712  struct extattr_list_fd_args /* {
713  int fd;
714  int attrnamespace;
715  void *data;
716  size_t nbytes;
717  } */ *uap;
718 {
719  struct file *fp;
720  int vfslocked, error;
721 
722  AUDIT_ARG_FD(uap->fd);
723  AUDIT_ARG_VALUE(uap->attrnamespace);
724  error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_LIST, &fp);
725  if (error)
726  return (error);
727 
728  vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
729  error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
730  uap->nbytes, td);
731 
732  fdrop(fp, td);
733  VFS_UNLOCK_GIANT(vfslocked);
734  return (error);
735 }
736 
737 int
739  struct thread*td;
740  struct extattr_list_file_args /* {
741  const char *path;
742  int attrnamespace;
743  void *data;
744  size_t nbytes;
745  } */ *uap;
746 {
747  struct nameidata nd;
748  int vfslocked, error;
749 
750  AUDIT_ARG_VALUE(uap->attrnamespace);
751  NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
752  uap->path, td);
753  error = namei(&nd);
754  if (error)
755  return (error);
756  NDFREE(&nd, NDF_ONLY_PNBUF);
757 
758  vfslocked = NDHASGIANT(&nd);
759  error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
760  uap->nbytes, td);
761 
762  vrele(nd.ni_vp);
763  VFS_UNLOCK_GIANT(vfslocked);
764  return (error);
765 }
766 
767 int
769  struct thread*td;
770  struct extattr_list_link_args /* {
771  const char *path;
772  int attrnamespace;
773  void *data;
774  size_t nbytes;
775  } */ *uap;
776 {
777  struct nameidata nd;
778  int vfslocked, error;
779 
780  AUDIT_ARG_VALUE(uap->attrnamespace);
781  NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
782  uap->path, td);
783  error = namei(&nd);
784  if (error)
785  return (error);
786  NDFREE(&nd, NDF_ONLY_PNBUF);
787 
788  vfslocked = NDHASGIANT(&nd);
789  error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
790  uap->nbytes, td);
791 
792  vrele(nd.ni_vp);
793  VFS_UNLOCK_GIANT(vfslocked);
794  return (error);
795 }
int getvnode(struct filedesc *fdp, int fd, cap_rights_t rights, struct file **fpp)
void NDFREE(struct nameidata *ndp, const u_int flags)
Definition: vfs_lookup.c:1091
int sys_extattr_set_file(struct thread *td, struct extattr_set_file_args *uap)
Definition: vfs_extattr.c:248
int sys_extattr_get_file(struct thread *td, struct extattr_get_file_args *uap)
Definition: vfs_extattr.c:428
void vn_finished_write(struct mount *mp)
Definition: vfs_vnops.c:1599
int sys_extattr_get_link(struct thread *td, struct extattr_get_link_args *uap)
Definition: vfs_extattr.c:465
int sys_extattr_list_fd(struct thread *td, struct extattr_list_fd_args *uap)
Definition: vfs_extattr.c:710
int sys_extattr_delete_file(struct thread *td, struct extattr_delete_file_args *uap)
Definition: vfs_extattr.c:578
__FBSDID("$BSDSUniX$")
int sys_extattr_delete_link(struct thread *td, struct extattr_delete_link_args *uap)
Definition: vfs_extattr.c:611
int sys_extattr_set_fd(struct thread *td, struct extattr_set_fd_args *uap)
Definition: vfs_extattr.c:213
int sys_extattr_delete_fd(struct thread *td, struct extattr_delete_fd_args *uap)
Definition: vfs_extattr.c:545
static int extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname, struct thread *td)
Definition: vfs_extattr.c:512
void vfs_unbusy(struct mount *mp)
Definition: vfs_subr.c:442
int namei(struct nameidata *ndp)
Definition: vfs_lookup.c:135
static int extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, void *data, size_t nbytes, struct thread *td)
Definition: vfs_extattr.c:164
int sys_extattr_list_file(struct thread *td, struct extattr_list_file_args *uap)
Definition: vfs_extattr.c:738
int sys_extattr_get_fd(struct thread *td, struct extattr_get_fd_args *uap)
Definition: vfs_extattr.c:393
int sys_extattr_set_link(struct thread *td, struct extattr_set_link_args *uap)
Definition: vfs_extattr.c:285
static int extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, void *data, size_t nbytes, struct thread *td)
Definition: vfs_extattr.c:332
int vfs_busy(struct mount *mp, int flags)
Definition: vfs_subr.c:395
void vrele(struct vnode *vp)
Definition: vfs_subr.c:2416
int vn_start_write(struct vnode *vp, struct mount **mpp, int flags)
Definition: vfs_vnops.c:1491
static int extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, size_t nbytes, struct thread *td)
Definition: vfs_extattr.c:654
int sys_extattrctl(struct thread *td, struct extattrctl_args *uap)
Definition: vfs_extattr.c:58
int sys_extattr_list_link(struct thread *td, struct extattr_list_link_args *uap)
Definition: vfs_extattr.c:768