1 /*-
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
35 */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD: releng/6.2/sys/kern/vfs_syscalls.c 164286 2006-11-14 20:42:41Z cvs2svn $");
39
40 #include "opt_compat.h"
41 #include "opt_mac.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/bio.h>
46 #include <sys/buf.h>
47 #include <sys/sysent.h>
48 #include <sys/mac.h>
49 #include <sys/malloc.h>
50 #include <sys/mount.h>
51 #include <sys/mutex.h>
52 #include <sys/sysproto.h>
53 #include <sys/namei.h>
54 #include <sys/filedesc.h>
55 #include <sys/kernel.h>
56 #include <sys/fcntl.h>
57 #include <sys/file.h>
58 #include <sys/limits.h>
59 #include <sys/linker.h>
60 #include <sys/stat.h>
61 #include <sys/sx.h>
62 #include <sys/unistd.h>
63 #include <sys/vnode.h>
64 #include <sys/proc.h>
65 #include <sys/dirent.h>
66 #include <sys/extattr.h>
67 #include <sys/jail.h>
68 #include <sys/syscallsubr.h>
69 #include <sys/sysctl.h>
70
71 #include <machine/stdarg.h>
72
73 #include <security/audit/audit.h>
74
75 #include <vm/vm.h>
76 #include <vm/vm_object.h>
77 #include <vm/vm_page.h>
78 #include <vm/uma.h>
79
80 static int chroot_refuse_vdir_fds(struct filedesc *fdp);
81 static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
82 static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
83 static int setfmode(struct thread *td, struct vnode *, int);
84 static int setfflags(struct thread *td, struct vnode *, int);
85 static int setutimes(struct thread *td, struct vnode *,
86 const struct timespec *, int, int);
87 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
88 struct thread *td);
89
90 static int extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
91 size_t nbytes, struct thread *td);
92
93 int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *);
94
95 /*
96 * The module initialization routine for POSIX asynchronous I/O will
97 * set this to the version of AIO that it implements. (Zero means
98 * that it is not implemented.) This value is used here by pathconf()
99 * and in kern_descrip.c by fpathconf().
100 */
101 int async_io_version;
102
103 /*
104 * Sync each mounted filesystem.
105 */
106 #ifndef _SYS_SYSPROTO_H_
107 struct sync_args {
108 int dummy;
109 };
110 #endif
111
112 #ifdef DEBUG
113 static int syncprt = 0;
114 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
115 #endif
116
117 /* ARGSUSED */
118 int
119 sync(td, uap)
120 struct thread *td;
121 struct sync_args *uap;
122 {
123 struct mount *mp, *nmp;
124 int asyncflag;
125
126 mtx_lock(&Giant);
127 mtx_lock(&mountlist_mtx);
128 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
129 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
130 nmp = TAILQ_NEXT(mp, mnt_list);
131 continue;
132 }
133 if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
134 vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
135 MNT_ILOCK(mp);
136 asyncflag = mp->mnt_flag & MNT_ASYNC;
137 mp->mnt_flag &= ~MNT_ASYNC;
138 MNT_IUNLOCK(mp);
139 vfs_msync(mp, MNT_NOWAIT);
140 VFS_SYNC(mp, MNT_NOWAIT, td);
141 MNT_ILOCK(mp);
142 mp->mnt_flag |= asyncflag;
143 MNT_IUNLOCK(mp);
144 vn_finished_write(mp);
145 }
146 mtx_lock(&mountlist_mtx);
147 nmp = TAILQ_NEXT(mp, mnt_list);
148 vfs_unbusy(mp, td);
149 }
150 mtx_unlock(&mountlist_mtx);
151 #if 0
152 /*
153 * XXX don't call vfs_bufstats() yet because that routine
154 * was not imported in the Lite2 merge.
155 */
156 #ifdef DIAGNOSTIC
157 if (syncprt)
158 vfs_bufstats();
159 #endif /* DIAGNOSTIC */
160 #endif
161 mtx_unlock(&Giant);
162 return (0);
163 }
164
165 /* XXX PRISON: could be per prison flag */
166 static int prison_quotas;
167 #if 0
168 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
169 #endif
170
171 /*
172 * Change filesystem quotas.
173 *
174 * MP SAFE
175 */
176 #ifndef _SYS_SYSPROTO_H_
177 struct quotactl_args {
178 char *path;
179 int cmd;
180 int uid;
181 caddr_t arg;
182 };
183 #endif
184 int
185 quotactl(td, uap)
186 struct thread *td;
187 register struct quotactl_args /* {
188 char *path;
189 int cmd;
190 int uid;
191 caddr_t arg;
192 } */ *uap;
193 {
194 struct mount *mp, *vmp;
195 int error;
196 struct nameidata nd;
197
198 AUDIT_ARG(cmd, uap->cmd);
199 AUDIT_ARG(uid, uap->uid);
200 if (jailed(td->td_ucred) && !prison_quotas)
201 return (EPERM);
202 mtx_lock(&Giant);
203 NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td);
204 if ((error = namei(&nd)) != 0) {
205 mtx_unlock(&Giant);
206 return (error);
207 }
208 NDFREE(&nd, NDF_ONLY_PNBUF);
209 error = vn_start_write(nd.ni_vp, &vmp, V_WAIT | PCATCH);
210 mp = nd.ni_vp->v_mount;
211 vrele(nd.ni_vp);
212 if (error) {
213 mtx_unlock(&Giant);
214 return (error);
215 }
216 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td);
217 vn_finished_write(vmp);
218 mtx_unlock(&Giant);
219 return (error);
220 }
221
222 /*
223 * Get filesystem statistics.
224 */
225 #ifndef _SYS_SYSPROTO_H_
226 struct statfs_args {
227 char *path;
228 struct statfs *buf;
229 };
230 #endif
231 int
232 statfs(td, uap)
233 struct thread *td;
234 register struct statfs_args /* {
235 char *path;
236 struct statfs *buf;
237 } */ *uap;
238 {
239 struct statfs sf;
240 int error;
241
242 error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
243 if (error == 0)
244 error = copyout(&sf, uap->buf, sizeof(sf));
245 return (error);
246 }
247
248 int
249 kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
250 struct statfs *buf)
251 {
252 struct mount *mp;
253 struct statfs *sp, sb;
254 int error;
255 struct nameidata nd;
256
257 mtx_lock(&Giant);
258 NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | LOCKLEAF, pathseg, path,
259 td);
260 error = namei(&nd);
261 if (error) {
262 mtx_unlock(&Giant);
263 return (error);
264 }
265 mp = nd.ni_vp->v_mount;
266 vfs_ref(mp);
267 NDFREE(&nd, NDF_ONLY_PNBUF);
268 vput(nd.ni_vp);
269 #ifdef MAC
270 error = mac_check_mount_stat(td->td_ucred, mp);
271 if (error)
272 goto out;
273 #endif
274 /*
275 * Set these in case the underlying filesystem fails to do so.
276 */
277 sp = &mp->mnt_stat;
278 sp->f_version = STATFS_VERSION;
279 sp->f_namemax = NAME_MAX;
280 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
281 error = VFS_STATFS(mp, sp, td);
282 if (error)
283 goto out;
284 if (suser(td)) {
285 bcopy(sp, &sb, sizeof(sb));
286 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
287 prison_enforce_statfs(td->td_ucred, mp, &sb);
288 sp = &sb;
289 }
290 *buf = *sp;
291 out:
292 vfs_rel(mp);
293 mtx_unlock(&Giant);
294 return (error);
295 }
296
297 /*
298 * Get filesystem statistics.
299 */
300 #ifndef _SYS_SYSPROTO_H_
301 struct fstatfs_args {
302 int fd;
303 struct statfs *buf;
304 };
305 #endif
306 int
307 fstatfs(td, uap)
308 struct thread *td;
309 register struct fstatfs_args /* {
310 int fd;
311 struct statfs *buf;
312 } */ *uap;
313 {
314 struct statfs sf;
315 int error;
316
317 error = kern_fstatfs(td, uap->fd, &sf);
318 if (error == 0)
319 error = copyout(&sf, uap->buf, sizeof(sf));
320 return (error);
321 }
322
323 int
324 kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
325 {
326 struct file *fp;
327 struct mount *mp;
328 struct statfs *sp, sb;
329 struct vnode *vp;
330 int error;
331
332 AUDIT_ARG(fd, fd);
333 error = getvnode(td->td_proc->p_fd, fd, &fp);
334 if (error)
335 return (error);
336 mtx_lock(&Giant);
337 vp = fp->f_vnode;
338 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
339 #ifdef AUDIT
340 AUDIT_ARG(vnode, vp, ARG_VNODE1);
341 #endif
342 mp = vp->v_mount;
343 if (mp)
344 vfs_ref(mp);
345 VOP_UNLOCK(vp, 0, td);
346 fdrop(fp, td);
347 if (vp->v_iflag & VI_DOOMED) {
348 if (mp)
349 vfs_rel(mp);
350 mtx_unlock(&Giant);
351 return (EBADF);
352 }
353 #ifdef MAC
354 error = mac_check_mount_stat(td->td_ucred, mp);
355 if (error)
356 goto out;
357 #endif
358 /*
359 * Set these in case the underlying filesystem fails to do so.
360 */
361 sp = &mp->mnt_stat;
362 sp->f_version = STATFS_VERSION;
363 sp->f_namemax = NAME_MAX;
364 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
365 error = VFS_STATFS(mp, sp, td);
366 if (error)
367 goto out;
368 if (suser(td)) {
369 bcopy(sp, &sb, sizeof(sb));
370 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
371 prison_enforce_statfs(td->td_ucred, mp, &sb);
372 sp = &sb;
373 }
374 *buf = *sp;
375 out:
376 vfs_rel(mp);
377 mtx_unlock(&Giant);
378 return (error);
379 }
380
381 /*
382 * Get statistics on all filesystems.
383 */
384 #ifndef _SYS_SYSPROTO_H_
385 struct getfsstat_args {
386 struct statfs *buf;
387 long bufsize;
388 int flags;
389 };
390 #endif
391 int
392 getfsstat(td, uap)
393 struct thread *td;
394 register struct getfsstat_args /* {
395 struct statfs *buf;
396 long bufsize;
397 int flags;
398 } */ *uap;
399 {
400
401 return (kern_getfsstat(td, &uap->buf, uap->bufsize, UIO_USERSPACE,
402 uap->flags));
403 }
404
405 /*
406 * If (bufsize > 0 && bufseg == UIO_SYSSPACE)
407 * The caller is responsible for freeing memory which will be allocated
408 * in '*buf'.
409 */
410 int
411 kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
412 enum uio_seg bufseg, int flags)
413 {
414 struct mount *mp, *nmp;
415 struct statfs *sfsp, *sp, sb;
416 size_t count, maxcount;
417 int error;
418
419 maxcount = bufsize / sizeof(struct statfs);
420 if (bufsize == 0)
421 sfsp = NULL;
422 else if (bufseg == UIO_USERSPACE)
423 sfsp = *buf;
424 else /* if (bufseg == UIO_SYSSPACE) */ {
425 count = 0;
426 mtx_lock(&mountlist_mtx);
427 TAILQ_FOREACH(mp, &mountlist, mnt_list) {
428 count++;
429 }
430 mtx_unlock(&mountlist_mtx);
431 if (maxcount > count)
432 maxcount = count;
433 sfsp = *buf = malloc(maxcount * sizeof(struct statfs), M_TEMP,
434 M_WAITOK);
435 }
436 count = 0;
437 mtx_lock(&Giant);
438 mtx_lock(&mountlist_mtx);
439 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
440 if (prison_canseemount(td->td_ucred, mp) != 0) {
441 nmp = TAILQ_NEXT(mp, mnt_list);
442 continue;
443 }
444 #ifdef MAC
445 if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
446 nmp = TAILQ_NEXT(mp, mnt_list);
447 continue;
448 }
449 #endif
450 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
451 nmp = TAILQ_NEXT(mp, mnt_list);
452 continue;
453 }
454 if (sfsp && count < maxcount) {
455 sp = &mp->mnt_stat;
456 /*
457 * Set these in case the underlying filesystem
458 * fails to do so.
459 */
460 sp->f_version = STATFS_VERSION;
461 sp->f_namemax = NAME_MAX;
462 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
463 /*
464 * If MNT_NOWAIT or MNT_LAZY is specified, do not
465 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
466 * overrides MNT_WAIT.
467 */
468 if (((flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
469 (flags & MNT_WAIT)) &&
470 (error = VFS_STATFS(mp, sp, td))) {
471 mtx_lock(&mountlist_mtx);
472 nmp = TAILQ_NEXT(mp, mnt_list);
473 vfs_unbusy(mp, td);
474 continue;
475 }
476 if (suser(td)) {
477 bcopy(sp, &sb, sizeof(sb));
478 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
479 prison_enforce_statfs(td->td_ucred, mp, &sb);
480 sp = &sb;
481 }
482 if (bufseg == UIO_SYSSPACE)
483 bcopy(sp, sfsp, sizeof(*sp));
484 else /* if (bufseg == UIO_USERSPACE) */ {
485 error = copyout(sp, sfsp, sizeof(*sp));
486 if (error) {
487 vfs_unbusy(mp, td);
488 mtx_unlock(&Giant);
489 return (error);
490 }
491 }
492 sfsp++;
493 }
494 count++;
495 mtx_lock(&mountlist_mtx);
496 nmp = TAILQ_NEXT(mp, mnt_list);
497 vfs_unbusy(mp, td);
498 }
499 mtx_unlock(&mountlist_mtx);
500 mtx_unlock(&Giant);
501 if (sfsp && count > maxcount)
502 td->td_retval[0] = maxcount;
503 else
504 td->td_retval[0] = count;
505 return (0);
506 }
507
508 #ifdef COMPAT_FREEBSD4
509 /*
510 * Get old format filesystem statistics.
511 */
512 static void cvtstatfs(struct statfs *, struct ostatfs *);
513
514 #ifndef _SYS_SYSPROTO_H_
515 struct freebsd4_statfs_args {
516 char *path;
517 struct ostatfs *buf;
518 };
519 #endif
520 int
521 freebsd4_statfs(td, uap)
522 struct thread *td;
523 struct freebsd4_statfs_args /* {
524 char *path;
525 struct ostatfs *buf;
526 } */ *uap;
527 {
528 struct ostatfs osb;
529 struct statfs sf;
530 int error;
531
532 error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
533 if (error)
534 return (error);
535 cvtstatfs(&sf, &osb);
536 return (copyout(&osb, uap->buf, sizeof(osb)));
537 }
538
539 /*
540 * Get filesystem statistics.
541 */
542 #ifndef _SYS_SYSPROTO_H_
543 struct freebsd4_fstatfs_args {
544 int fd;
545 struct ostatfs *buf;
546 };
547 #endif
548 int
549 freebsd4_fstatfs(td, uap)
550 struct thread *td;
551 struct freebsd4_fstatfs_args /* {
552 int fd;
553 struct ostatfs *buf;
554 } */ *uap;
555 {
556 struct ostatfs osb;
557 struct statfs sf;
558 int error;
559
560 error = kern_fstatfs(td, uap->fd, &sf);
561 if (error)
562 return (error);
563 cvtstatfs(&sf, &osb);
564 return (copyout(&osb, uap->buf, sizeof(osb)));
565 }
566
567 /*
568 * Get statistics on all filesystems.
569 */
570 #ifndef _SYS_SYSPROTO_H_
571 struct freebsd4_getfsstat_args {
572 struct ostatfs *buf;
573 long bufsize;
574 int flags;
575 };
576 #endif
577 int
578 freebsd4_getfsstat(td, uap)
579 struct thread *td;
580 register struct freebsd4_getfsstat_args /* {
581 struct ostatfs *buf;
582 long bufsize;
583 int flags;
584 } */ *uap;
585 {
586 struct statfs *buf, *sp;
587 struct ostatfs osb;
588 size_t count, size;
589 int error;
590
591 count = uap->bufsize / sizeof(struct ostatfs);
592 size = count * sizeof(struct statfs);
593 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
594 if (size > 0) {
595 count = td->td_retval[0];
596 sp = buf;
597 while (count > 0 && error == 0) {
598 cvtstatfs(sp, &osb);
599 error = copyout(&osb, uap->buf, sizeof(osb));
600 sp++;
601 uap->buf++;
602 count--;
603 }
604 free(buf, M_TEMP);
605 }
606 return (error);
607 }
608
609 /*
610 * Implement fstatfs() for (NFS) file handles.
611 */
612 #ifndef _SYS_SYSPROTO_H_
613 struct freebsd4_fhstatfs_args {
614 struct fhandle *u_fhp;
615 struct ostatfs *buf;
616 };
617 #endif
618 int
619 freebsd4_fhstatfs(td, uap)
620 struct thread *td;
621 struct freebsd4_fhstatfs_args /* {
622 struct fhandle *u_fhp;
623 struct ostatfs *buf;
624 } */ *uap;
625 {
626 struct ostatfs osb;
627 struct statfs sf;
628 fhandle_t fh;
629 int error;
630
631 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
632 if (error)
633 return (error);
634 error = kern_fhstatfs(td, fh, &sf);
635 if (error)
636 return (error);
637 cvtstatfs(&sf, &osb);
638 return (copyout(&osb, uap->buf, sizeof(osb)));
639 }
640
641 /*
642 * Convert a new format statfs structure to an old format statfs structure.
643 */
644 static void
645 cvtstatfs(nsp, osp)
646 struct statfs *nsp;
647 struct ostatfs *osp;
648 {
649
650 bzero(osp, sizeof(*osp));
651 osp->f_bsize = MIN(nsp->f_bsize, LONG_MAX);
652 osp->f_iosize = MIN(nsp->f_iosize, LONG_MAX);
653 osp->f_blocks = MIN(nsp->f_blocks, LONG_MAX);
654 osp->f_bfree = MIN(nsp->f_bfree, LONG_MAX);
655 osp->f_bavail = MIN(nsp->f_bavail, LONG_MAX);
656 osp->f_files = MIN(nsp->f_files, LONG_MAX);
657 osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX);
658 osp->f_owner = nsp->f_owner;
659 osp->f_type = nsp->f_type;
660 osp->f_flags = nsp->f_flags;
661 osp->f_syncwrites = MIN(nsp->f_syncwrites, LONG_MAX);
662 osp->f_asyncwrites = MIN(nsp->f_asyncwrites, LONG_MAX);
663 osp->f_syncreads = MIN(nsp->f_syncreads, LONG_MAX);
664 osp->f_asyncreads = MIN(nsp->f_asyncreads, LONG_MAX);
665 strlcpy(osp->f_fstypename, nsp->f_fstypename,
666 MIN(MFSNAMELEN, OMFSNAMELEN));
667 strlcpy(osp->f_mntonname, nsp->f_mntonname,
668 MIN(MNAMELEN, OMNAMELEN));
669 strlcpy(osp->f_mntfromname, nsp->f_mntfromname,
670 MIN(MNAMELEN, OMNAMELEN));
671 osp->f_fsid = nsp->f_fsid;
672 }
673 #endif /* COMPAT_FREEBSD4 */
674
675 /*
676 * Change current working directory to a given file descriptor.
677 */
678 #ifndef _SYS_SYSPROTO_H_
679 struct fchdir_args {
680 int fd;
681 };
682 #endif
683 int
684 fchdir(td, uap)
685 struct thread *td;
686 struct fchdir_args /* {
687 int fd;
688 } */ *uap;
689 {
690 register struct filedesc *fdp = td->td_proc->p_fd;
691 struct vnode *vp, *tdp, *vpold;
692 struct mount *mp;
693 struct file *fp;
694 int vfslocked;
695 int error;
696
697 AUDIT_ARG(fd, uap->fd);
698 if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
699 return (error);
700 vp = fp->f_vnode;
701 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
702 VREF(vp);
703 fdrop(fp, td);
704 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
705 AUDIT_ARG(vnode, vp, ARG_VNODE1);
706 if (vp->v_type != VDIR)
707 error = ENOTDIR;
708 #ifdef MAC
709 else if ((error = mac_check_vnode_chdir(td->td_ucred, vp)) != 0) {
710 }
711 #endif
712 else
713 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
714 while (!error && (mp = vp->v_mountedhere) != NULL) {
715 int tvfslocked;
716 if (vfs_busy(mp, 0, 0, td))
717 continue;
718 tvfslocked = VFS_LOCK_GIANT(mp);
719 error = VFS_ROOT(mp, LK_EXCLUSIVE, &tdp, td);
720 vfs_unbusy(mp, td);
721 if (error) {
722 VFS_UNLOCK_GIANT(tvfslocked);
723 break;
724 }
725 vput(vp);
726 VFS_UNLOCK_GIANT(vfslocked);
727 vp = tdp;
728 vfslocked = tvfslocked;
729 }
730 if (error) {
731 vput(vp);
732 VFS_UNLOCK_GIANT(vfslocked);
733 return (error);
734 }
735 VOP_UNLOCK(vp, 0, td);
736 VFS_UNLOCK_GIANT(vfslocked);
737 FILEDESC_LOCK_FAST(fdp);
738 vpold = fdp->fd_cdir;
739 fdp->fd_cdir = vp;
740 FILEDESC_UNLOCK_FAST(fdp);
741 vfslocked = VFS_LOCK_GIANT(vpold->v_mount);
742 vrele(vpold);
743 VFS_UNLOCK_GIANT(vfslocked);
744 return (0);
745 }
746
747 /*
748 * Change current working directory (``.'').
749 */
750 #ifndef _SYS_SYSPROTO_H_
751 struct chdir_args {
752 char *path;
753 };
754 #endif
755 int
756 chdir(td, uap)
757 struct thread *td;
758 struct chdir_args /* {
759 char *path;
760 } */ *uap;
761 {
762
763 return (kern_chdir(td, uap->path, UIO_USERSPACE));
764 }
765
766 int
767 kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
768 {
769 register struct filedesc *fdp = td->td_proc->p_fd;
770 int error;
771 struct nameidata nd;
772 struct vnode *vp;
773 int vfslocked;
774
775 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1 | MPSAFE,
776 pathseg, path, td);
777 if ((error = namei(&nd)) != 0)
778 return (error);
779 vfslocked = NDHASGIANT(&nd);
780 if ((error = change_dir(nd.ni_vp, td)) != 0) {
781 vput(nd.ni_vp);
782 VFS_UNLOCK_GIANT(vfslocked);
783 NDFREE(&nd, NDF_ONLY_PNBUF);
784 return (error);
785 }
786 VOP_UNLOCK(nd.ni_vp, 0, td);
787 VFS_UNLOCK_GIANT(vfslocked);
788 NDFREE(&nd, NDF_ONLY_PNBUF);
789 FILEDESC_LOCK_FAST(fdp);
790 vp = fdp->fd_cdir;
791 fdp->fd_cdir = nd.ni_vp;
792 FILEDESC_UNLOCK_FAST(fdp);
793 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
794 vrele(vp);
795 VFS_UNLOCK_GIANT(vfslocked);
796 return (0);
797 }
798
799 /*
800 * Helper function for raised chroot(2) security function: Refuse if
801 * any filedescriptors are open directories.
802 */
803 static int
804 chroot_refuse_vdir_fds(fdp)
805 struct filedesc *fdp;
806 {
807 struct vnode *vp;
808 struct file *fp;
809 int fd;
810
811 FILEDESC_LOCK_ASSERT(fdp, MA_OWNED);
812 for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
813 fp = fget_locked(fdp, fd);
814 if (fp == NULL)
815 continue;
816 if (fp->f_type == DTYPE_VNODE) {
817 vp = fp->f_vnode;
818 if (vp->v_type == VDIR)
819 return (EPERM);
820 }
821 }
822 return (0);
823 }
824
825 /*
826 * This sysctl determines if we will allow a process to chroot(2) if it
827 * has a directory open:
828 * 0: disallowed for all processes.
829 * 1: allowed for processes that were not already chroot(2)'ed.
830 * 2: allowed for all processes.
831 */
832
833 static int chroot_allow_open_directories = 1;
834
835 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
836 &chroot_allow_open_directories, 0, "");
837
838 /*
839 * Change notion of root (``/'') directory.
840 */
841 #ifndef _SYS_SYSPROTO_H_
842 struct chroot_args {
843 char *path;
844 };
845 #endif
846 int
847 chroot(td, uap)
848 struct thread *td;
849 struct chroot_args /* {
850 char *path;
851 } */ *uap;
852 {
853 int error;
854 struct nameidata nd;
855 int vfslocked;
856
857 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
858 if (error)
859 return (error);
860 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
861 UIO_USERSPACE, uap->path, td);
862 error = namei(&nd);
863 if (error)
864 goto error;
865 vfslocked = NDHASGIANT(&nd);
866 if ((error = change_dir(nd.ni_vp, td)) != 0)
867 goto e_vunlock;
868 #ifdef MAC
869 if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp)))
870 goto e_vunlock;
871 #endif
872 VOP_UNLOCK(nd.ni_vp, 0, td);
873 error = change_root(nd.ni_vp, td);
874 vrele(nd.ni_vp);
875 VFS_UNLOCK_GIANT(vfslocked);
876 NDFREE(&nd, NDF_ONLY_PNBUF);
877 return (error);
878 e_vunlock:
879 vput(nd.ni_vp);
880 VFS_UNLOCK_GIANT(vfslocked);
881 error:
882 NDFREE(&nd, NDF_ONLY_PNBUF);
883 return (error);
884 }
885
886 /*
887 * Common routine for chroot and chdir. Callers must provide a locked vnode
888 * instance.
889 */
890 int
891 change_dir(vp, td)
892 struct vnode *vp;
893 struct thread *td;
894 {
895 int error;
896
897 ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked");
898 if (vp->v_type != VDIR)
899 return (ENOTDIR);
900 #ifdef MAC
901 error = mac_check_vnode_chdir(td->td_ucred, vp);
902 if (error)
903 return (error);
904 #endif
905 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
906 return (error);
907 }
908
909 /*
910 * Common routine for kern_chroot() and jail_attach(). The caller is
911 * responsible for invoking suser() and mac_check_chroot() to authorize this
912 * operation.
913 */
914 int
915 change_root(vp, td)
916 struct vnode *vp;
917 struct thread *td;
918 {
919 struct filedesc *fdp;
920 struct vnode *oldvp;
921 int vfslocked;
922 int error;
923
924 VFS_ASSERT_GIANT(vp->v_mount);
925 fdp = td->td_proc->p_fd;
926 FILEDESC_LOCK(fdp);
927 if (chroot_allow_open_directories == 0 ||
928 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
929 error = chroot_refuse_vdir_fds(fdp);
930 if (error) {
931 FILEDESC_UNLOCK(fdp);
932 return (error);
933 }
934 }
935 oldvp = fdp->fd_rdir;
936 fdp->fd_rdir = vp;
937 VREF(fdp->fd_rdir);
938 if (!fdp->fd_jdir) {
939 fdp->fd_jdir = vp;
940 VREF(fdp->fd_jdir);
941 }
942 FILEDESC_UNLOCK(fdp);
943 vfslocked = VFS_LOCK_GIANT(oldvp->v_mount);
944 vrele(oldvp);
945 VFS_UNLOCK_GIANT(vfslocked);
946 return (0);
947 }
948
949 /*
950 * Check permissions, allocate an open file structure,
951 * and call the device open routine if any.
952 *
953 * MP SAFE
954 */
955 #ifndef _SYS_SYSPROTO_H_
956 struct open_args {
957 char *path;
958 int flags;
959 int mode;
960 };
961 #endif
962 int
963 open(td, uap)
964 struct thread *td;
965 register struct open_args /* {
966 char *path;
967 int flags;
968 int mode;
969 } */ *uap;
970 {
971 int error;
972
973 error = kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode);
974 if (mtx_owned(&Giant))
975 printf("open: %s: %d\n", uap->path, error);
976 return (error);
977 }
978
979 int
980 kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags,
981 int mode)
982 {
983 struct proc *p = td->td_proc;
984 struct filedesc *fdp = p->p_fd;
985 struct file *fp;
986 struct vnode *vp;
987 struct vattr vat;
988 struct mount *mp;
989 int cmode;
990 struct file *nfp;
991 int type, indx, error;
992 struct flock lf;
993 struct nameidata nd;
994 int vfslocked;
995
996 AUDIT_ARG(fflags, flags);
997 AUDIT_ARG(mode, mode);
998 if ((flags & O_ACCMODE) == O_ACCMODE)
999 return (EINVAL);
1000 flags = FFLAGS(flags);
1001 error = falloc(td, &nfp, &indx);
1002 if (error)
1003 return (error);
1004 /* An extra reference on `nfp' has been held for us by falloc(). */
1005 fp = nfp;
1006 cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
1007 NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, td);
1008 td->td_dupfd = -1; /* XXX check for fdopen */
1009 error = vn_open(&nd, &flags, cmode, indx);
1010 if (error) {
1011 /*
1012 * If the vn_open replaced the method vector, something
1013 * wonderous happened deep below and we just pass it up
1014 * pretending we know what we do.
1015 */
1016 if (error == ENXIO && fp->f_ops != &badfileops) {
1017 fdrop(fp, td);
1018 td->td_retval[0] = indx;
1019 return (0);
1020 }
1021
1022 /*
1023 * release our own reference
1024 */
1025 fdrop(fp, td);
1026
1027 /*
1028 * handle special fdopen() case. bleh. dupfdopen() is
1029 * responsible for dropping the old contents of ofiles[indx]
1030 * if it succeeds.
1031 */
1032 if ((error == ENODEV || error == ENXIO) &&
1033 td->td_dupfd >= 0 && /* XXX from fdopen */
1034 (error =
1035 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
1036 td->td_retval[0] = indx;
1037 return (0);
1038 }
1039 /*
1040 * Clean up the descriptor, but only if another thread hadn't
1041 * replaced or closed it.
1042 */
1043 fdclose(fdp, fp, indx, td);
1044
1045 if (error == ERESTART)
1046 error = EINTR;
1047 return (error);
1048 }
1049 td->td_dupfd = 0;
1050 vfslocked = NDHASGIANT(&nd);
1051 NDFREE(&nd, NDF_ONLY_PNBUF);
1052 vp = nd.ni_vp;
1053
1054 /*
1055 * There should be 2 references on the file, one from the descriptor
1056 * table, and one for us.
1057 *
1058 * Handle the case where someone closed the file (via its file
1059 * descriptor) while we were blocked. The end result should look
1060 * like opening the file succeeded but it was immediately closed.
1061 * We call vn_close() manually because we haven't yet hooked up
1062 * the various 'struct file' fields.
1063 */
1064 FILEDESC_LOCK(fdp);
1065 FILE_LOCK(fp);
1066 if (fp->f_count == 1) {
1067 mp = vp->v_mount;
1068 KASSERT(fdp->fd_ofiles[indx] != fp,
1069 ("Open file descriptor lost all refs"));
1070 FILE_UNLOCK(fp);
1071 FILEDESC_UNLOCK(fdp);
1072 VOP_UNLOCK(vp, 0, td);
1073 vn_close(vp, flags & FMASK, fp->f_cred, td);
1074 VFS_UNLOCK_GIANT(vfslocked);
1075 fdrop(fp, td);
1076 td->td_retval[0] = indx;
1077 return (0);
1078 }
1079 fp->f_vnode = vp;
1080 if (fp->f_data == NULL)
1081 fp->f_data = vp;
1082 fp->f_flag = flags & FMASK;
1083 if (fp->f_ops == &badfileops)
1084 fp->f_ops = &vnops;
1085 fp->f_seqcount = 1;
1086 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1087 FILE_UNLOCK(fp);
1088 FILEDESC_UNLOCK(fdp);
1089
1090 VOP_UNLOCK(vp, 0, td);
1091 if (flags & (O_EXLOCK | O_SHLOCK)) {
1092 lf.l_whence = SEEK_SET;
1093 lf.l_start = 0;
1094 lf.l_len = 0;
1095 if (flags & O_EXLOCK)
1096 lf.l_type = F_WRLCK;
1097 else
1098 lf.l_type = F_RDLCK;
1099 type = F_FLOCK;
1100 if ((flags & FNONBLOCK) == 0)
1101 type |= F_WAIT;
1102 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
1103 type)) != 0)
1104 goto bad;
1105 fp->f_flag |= FHASLOCK;
1106 }
1107 if (flags & O_TRUNC) {
1108 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1109 goto bad;
1110 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1111 VATTR_NULL(&vat);
1112 vat.va_size = 0;
1113 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1114 #ifdef MAC
1115 error = mac_check_vnode_write(td->td_ucred, fp->f_cred, vp);
1116 if (error == 0)
1117 #endif
1118 error = VOP_SETATTR(vp, &vat, td->td_ucred, td);
1119 VOP_UNLOCK(vp, 0, td);
1120 vn_finished_write(mp);
1121 if (error)
1122 goto bad;
1123 }
1124 VFS_UNLOCK_GIANT(vfslocked);
1125 /*
1126 * Release our private reference, leaving the one associated with
1127 * the descriptor table intact.
1128 */
1129 fdrop(fp, td);
1130 td->td_retval[0] = indx;
1131 return (0);
1132 bad:
1133 VFS_UNLOCK_GIANT(vfslocked);
1134 fdclose(fdp, fp, indx, td);
1135 fdrop(fp, td);
1136 return (error);
1137 }
1138
1139 #ifdef COMPAT_43
1140 /*
1141 * Create a file.
1142 *
1143 * MP SAFE
1144 */
1145 #ifndef _SYS_SYSPROTO_H_
1146 struct ocreat_args {
1147 char *path;
1148 int mode;
1149 };
1150 #endif
1151 int
1152 ocreat(td, uap)
1153 struct thread *td;
1154 register struct ocreat_args /* {
1155 char *path;
1156 int mode;
1157 } */ *uap;
1158 {
1159
1160 return (kern_open(td, uap->path, UIO_USERSPACE,
1161 O_WRONLY | O_CREAT | O_TRUNC, uap->mode));
1162 }
1163 #endif /* COMPAT_43 */
1164
1165 /*
1166 * Create a special file.
1167 */
1168 #ifndef _SYS_SYSPROTO_H_
1169 struct mknod_args {
1170 char *path;
1171 int mode;
1172 int dev;
1173 };
1174 #endif
1175 int
1176 mknod(td, uap)
1177 struct thread *td;
1178 register struct mknod_args /* {
1179 char *path;
1180 int mode;
1181 int dev;
1182 } */ *uap;
1183 {
1184
1185 return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev));
1186 }
1187
1188 int
1189 kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
1190 int dev)
1191 {
1192 struct vnode *vp;
1193 struct mount *mp;
1194 struct vattr vattr;
1195 int error;
1196 int whiteout = 0;
1197 struct nameidata nd;
1198 int vfslocked;
1199
1200 AUDIT_ARG(mode, mode);
1201 AUDIT_ARG(dev, dev);
1202 switch (mode & S_IFMT) {
1203 case S_IFCHR:
1204 case S_IFBLK:
1205 error = suser(td);
1206 break;
1207 default:
1208 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
1209 break;
1210 }
1211 if (error)
1212 return (error);
1213 restart:
1214 bwillwrite();
1215 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
1216 pathseg, path, td);
1217 if ((error = namei(&nd)) != 0)
1218 return (error);
1219 vfslocked = NDHASGIANT(&nd);
1220 vp = nd.ni_vp;
1221 if (vp != NULL) {
1222 NDFREE(&nd, NDF_ONLY_PNBUF);
1223 if (vp == nd.ni_dvp)
1224 vrele(nd.ni_dvp);
1225 else
1226 vput(nd.ni_dvp);
1227 vrele(vp);
1228 VFS_UNLOCK_GIANT(vfslocked);
1229 return (EEXIST);
1230 } else {
1231 VATTR_NULL(&vattr);
1232 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1233 vattr.va_mode = (mode & ALLPERMS) &
1234 ~td->td_proc->p_fd->fd_cmask;
1235 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1236 vattr.va_rdev = dev;
1237 whiteout = 0;
1238
1239 switch (mode & S_IFMT) {
1240 case S_IFMT: /* used by badsect to flag bad sectors */
1241 vattr.va_type = VBAD;
1242 break;
1243 case S_IFCHR:
1244 vattr.va_type = VCHR;
1245 break;
1246 case S_IFBLK:
1247 vattr.va_type = VBLK;
1248 break;
1249 case S_IFWHT:
1250 whiteout = 1;
1251 break;
1252 default:
1253 error = EINVAL;
1254 break;
1255 }
1256 }
1257 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1258 NDFREE(&nd, NDF_ONLY_PNBUF);
1259 vput(nd.ni_dvp);
1260 VFS_UNLOCK_GIANT(vfslocked);
1261 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1262 return (error);
1263 goto restart;
1264 }
1265 #ifdef MAC
1266 if (error == 0 && !whiteout)
1267 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp,
1268 &nd.ni_cnd, &vattr);
1269 #endif
1270 if (!error) {
1271 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1272 if (whiteout)
1273 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1274 else {
1275 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1276 &nd.ni_cnd, &vattr);
1277 if (error == 0)
1278 vput(nd.ni_vp);
1279 }
1280 }
1281 NDFREE(&nd, NDF_ONLY_PNBUF);
1282 vput(nd.ni_dvp);
1283 vn_finished_write(mp);
1284 VFS_UNLOCK_GIANT(vfslocked);
1285 return (error);
1286 }
1287
1288 /*
1289 * Create a named pipe.
1290 */
1291 #ifndef _SYS_SYSPROTO_H_
1292 struct mkfifo_args {
1293 char *path;
1294 int mode;
1295 };
1296 #endif
1297 int
1298 mkfifo(td, uap)
1299 struct thread *td;
1300 register struct mkfifo_args /* {
1301 char *path;
1302 int mode;
1303 } */ *uap;
1304 {
1305
1306 return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode));
1307 }
1308
1309 int
1310 kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode)
1311 {
1312 struct mount *mp;
1313 struct vattr vattr;
1314 int error;
1315 struct nameidata nd;
1316 int vfslocked;
1317
1318 AUDIT_ARG(mode, mode);
1319 restart:
1320 bwillwrite();
1321 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
1322 pathseg, path, td);
1323 if ((error = namei(&nd)) != 0)
1324 return (error);
1325 vfslocked = NDHASGIANT(&nd);
1326 if (nd.ni_vp != NULL) {
1327 NDFREE(&nd, NDF_ONLY_PNBUF);
1328 if (nd.ni_vp == nd.ni_dvp)
1329 vrele(nd.ni_dvp);
1330 else
1331 vput(nd.ni_dvp);
1332 vrele(nd.ni_vp);
1333 VFS_UNLOCK_GIANT(vfslocked);
1334 return (EEXIST);
1335 }
1336 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1337 NDFREE(&nd, NDF_ONLY_PNBUF);
1338 vput(nd.ni_dvp);
1339 VFS_UNLOCK_GIANT(vfslocked);
1340 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1341 return (error);
1342 goto restart;
1343 }
1344 VATTR_NULL(&vattr);
1345 vattr.va_type = VFIFO;
1346 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1347 vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask;
1348 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1349 #ifdef MAC
1350 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1351 &vattr);
1352 if (error)
1353 goto out;
1354 #endif
1355 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1356 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1357 if (error == 0)
1358 vput(nd.ni_vp);
1359 #ifdef MAC
1360 out:
1361 #endif
1362 vput(nd.ni_dvp);
1363 vn_finished_write(mp);
1364 VFS_UNLOCK_GIANT(vfslocked);
1365 NDFREE(&nd, NDF_ONLY_PNBUF);
1366 return (error);
1367 }
1368
1369 /*
1370 * Make a hard file link.
1371 */
1372 #ifndef _SYS_SYSPROTO_H_
1373 struct link_args {
1374 char *path;
1375 char *link;
1376 };
1377 #endif
1378 int
1379 link(td, uap)
1380 struct thread *td;
1381 register struct link_args /* {
1382 char *path;
1383 char *link;
1384 } */ *uap;
1385 {
1386 int error;
1387
1388 error = kern_link(td, uap->path, uap->link, UIO_USERSPACE);
1389 return (error);
1390 }
1391
1392 SYSCTL_DECL(_security_bsd);
1393
1394 static int hardlink_check_uid = 0;
1395 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
1396 &hardlink_check_uid, 0,
1397 "Unprivileged processes cannot create hard links to files owned by other "
1398 "users");
1399 static int hardlink_check_gid = 0;
1400 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
1401 &hardlink_check_gid, 0,
1402 "Unprivileged processes cannot create hard links to files owned by other "
1403 "groups");
1404
1405 static int
1406 can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
1407 {
1408 struct vattr va;
1409 int error;
1410
1411 if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
1412 return (0);
1413
1414 if (!hardlink_check_uid && !hardlink_check_gid)
1415 return (0);
1416
1417 error = VOP_GETATTR(vp, &va, cred, td);
1418 if (error != 0)
1419 return (error);
1420
1421 if (hardlink_check_uid) {
1422 if (cred->cr_uid != va.va_uid)
1423 return (EPERM);
1424 }
1425
1426 if (hardlink_check_gid) {
1427 if (!groupmember(va.va_gid, cred))
1428 return (EPERM);
1429 }
1430
1431 return (0);
1432 }
1433
1434 int
1435 kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
1436 {
1437 struct vnode *vp;
1438 struct mount *mp;
1439 struct nameidata nd;
1440 int vfslocked;
1441 int lvfslocked;
1442 int error;
1443
1444 bwillwrite();
1445 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, segflg, path, td);
1446 if ((error = namei(&nd)) != 0)
1447 return (error);
1448 vfslocked = NDHASGIANT(&nd);
1449 NDFREE(&nd, NDF_ONLY_PNBUF);
1450 vp = nd.ni_vp;
1451 if (vp->v_type == VDIR) {
1452 vrele(vp);
1453 VFS_UNLOCK_GIANT(vfslocked);
1454 return (EPERM); /* POSIX */
1455 }
1456 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
1457 vrele(vp);
1458 VFS_UNLOCK_GIANT(vfslocked);
1459 return (error);
1460 }
1461 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE2,
1462 segflg, link, td);
1463 if ((error = namei(&nd)) == 0) {
1464 lvfslocked = NDHASGIANT(&nd);
1465 if (nd.ni_vp != NULL) {
1466 if (nd.ni_dvp == nd.ni_vp)
1467 vrele(nd.ni_dvp);
1468 else
1469 vput(nd.ni_dvp);
1470 vrele(nd.ni_vp);
1471 error = EEXIST;
1472 } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td))
1473 == 0) {
1474 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1475 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1476 error = can_hardlink(vp, td, td->td_ucred);
1477 if (error == 0)
1478 #ifdef MAC
1479 error = mac_check_vnode_link(td->td_ucred,
1480 nd.ni_dvp, vp, &nd.ni_cnd);
1481 if (error == 0)
1482 #endif
1483 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1484 VOP_UNLOCK(vp, 0, td);
1485 vput(nd.ni_dvp);
1486 }
1487 NDFREE(&nd, NDF_ONLY_PNBUF);
1488 VFS_UNLOCK_GIANT(lvfslocked);
1489 }
1490 vrele(vp);
1491 vn_finished_write(mp);
1492 VFS_UNLOCK_GIANT(vfslocked);
1493 return (error);
1494 }
1495
1496 /*
1497 * Make a symbolic link.
1498 */
1499 #ifndef _SYS_SYSPROTO_H_
1500 struct symlink_args {
1501 char *path;
1502 char *link;
1503 };
1504 #endif
1505 int
1506 symlink(td, uap)
1507 struct thread *td;
1508 register struct symlink_args /* {
1509 char *path;
1510 char *link;
1511 } */ *uap;
1512 {
1513
1514 return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE));
1515 }
1516
1517 int
1518 kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg)
1519 {
1520 struct mount *mp;
1521 struct vattr vattr;
1522 char *syspath;
1523 int error;
1524 struct nameidata nd;
1525 int vfslocked;
1526
1527 if (segflg == UIO_SYSSPACE) {
1528 syspath = path;
1529 } else {
1530 syspath = uma_zalloc(namei_zone, M_WAITOK);
1531 if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0)
1532 goto out;
1533 }
1534 AUDIT_ARG(text, syspath);
1535 restart:
1536 bwillwrite();
1537 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
1538 segflg, link, td);
1539 if ((error = namei(&nd)) != 0)
1540 goto out;
1541 vfslocked = NDHASGIANT(&nd);
1542 if (nd.ni_vp) {
1543 NDFREE(&nd, NDF_ONLY_PNBUF);
1544 if (nd.ni_vp == nd.ni_dvp)
1545 vrele(nd.ni_dvp);
1546 else
1547 vput(nd.ni_dvp);
1548 vrele(nd.ni_vp);
1549 VFS_UNLOCK_GIANT(vfslocked);
1550 error = EEXIST;
1551 goto out;
1552 }
1553 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1554 NDFREE(&nd, NDF_ONLY_PNBUF);
1555 vput(nd.ni_dvp);
1556 VFS_UNLOCK_GIANT(vfslocked);
1557 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1558 goto out;
1559 goto restart;
1560 }
1561 VATTR_NULL(&vattr);
1562 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1563 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
1564 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1565 #ifdef MAC
1566 vattr.va_type = VLNK;
1567 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1568 &vattr);
1569 if (error)
1570 goto out2;
1571 #endif
1572 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1573 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
1574 if (error == 0)
1575 vput(nd.ni_vp);
1576 #ifdef MAC
1577 out2:
1578 #endif
1579 NDFREE(&nd, NDF_ONLY_PNBUF);
1580 vput(nd.ni_dvp);
1581 vn_finished_write(mp);
1582 VFS_UNLOCK_GIANT(vfslocked);
1583 out:
1584 if (segflg != UIO_SYSSPACE)
1585 uma_zfree(namei_zone, syspath);
1586 return (error);
1587 }
1588
1589 /*
1590 * Delete a whiteout from the filesystem.
1591 */
1592 int
1593 undelete(td, uap)
1594 struct thread *td;
1595 register struct undelete_args /* {
1596 char *path;
1597 } */ *uap;
1598 {
1599 int error;
1600 struct mount *mp;
1601 struct nameidata nd;
1602 int vfslocked;
1603
1604 restart:
1605 bwillwrite();
1606 NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | MPSAFE | AUDITVNODE1,
1607 UIO_USERSPACE, uap->path, td);
1608 error = namei(&nd);
1609 if (error)
1610 return (error);
1611 vfslocked = NDHASGIANT(&nd);
1612
1613 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1614 NDFREE(&nd, NDF_ONLY_PNBUF);
1615 if (nd.ni_vp == nd.ni_dvp)
1616 vrele(nd.ni_dvp);
1617 else
1618 vput(nd.ni_dvp);
1619 if (nd.ni_vp)
1620 vrele(nd.ni_vp);
1621 VFS_UNLOCK_GIANT(vfslocked);
1622 return (EEXIST);
1623 }
1624 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1625 NDFREE(&nd, NDF_ONLY_PNBUF);
1626 vput(nd.ni_dvp);
1627 VFS_UNLOCK_GIANT(vfslocked);
1628 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1629 return (error);
1630 goto restart;
1631 }
1632 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1633 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1634 NDFREE(&nd, NDF_ONLY_PNBUF);
1635 vput(nd.ni_dvp);
1636 vn_finished_write(mp);
1637 VFS_UNLOCK_GIANT(vfslocked);
1638 return (error);
1639 }
1640
1641 /*
1642 * Delete a name from the filesystem.
1643 */
1644 #ifndef _SYS_SYSPROTO_H_
1645 struct unlink_args {
1646 char *path;
1647 };
1648 #endif
1649 int
1650 unlink(td, uap)
1651 struct thread *td;
1652 struct unlink_args /* {
1653 char *path;
1654 } */ *uap;
1655 {
1656 int error;
1657
1658 error = kern_unlink(td, uap->path, UIO_USERSPACE);
1659 return (error);
1660 }
1661
1662 int
1663 kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
1664 {
1665 struct mount *mp;
1666 struct vnode *vp;
1667 int error;
1668 struct nameidata nd;
1669 int vfslocked;
1670
1671 restart:
1672 bwillwrite();
1673 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1,
1674 pathseg, path, td);
1675 if ((error = namei(&nd)) != 0)
1676 return (error == EINVAL ? EPERM : error);
1677 vfslocked = NDHASGIANT(&nd);
1678 vp = nd.ni_vp;
1679 if (vp->v_type == VDIR)
1680 error = EPERM; /* POSIX */
1681 else {
1682 /*
1683 * The root of a mounted filesystem cannot be deleted.
1684 *
1685 * XXX: can this only be a VDIR case?
1686 */
1687 if (vp->v_vflag & VV_ROOT)
1688 error = EBUSY;
1689 }
1690 if (error == 0) {
1691 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1692 NDFREE(&nd, NDF_ONLY_PNBUF);
1693 vput(nd.ni_dvp);
1694 if (vp == nd.ni_dvp)
1695 vrele(vp);
1696 else
1697 vput(vp);
1698 VFS_UNLOCK_GIANT(vfslocked);
1699 if ((error = vn_start_write(NULL, &mp,
1700 V_XSLEEP | PCATCH)) != 0)
1701 return (error);
1702 goto restart;
1703 }
1704 #ifdef MAC
1705 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
1706 &nd.ni_cnd);
1707 if (error)
1708 goto out;
1709 #endif
1710 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1711 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1712 #ifdef MAC
1713 out:
1714 #endif
1715 vn_finished_write(mp);
1716 }
1717 NDFREE(&nd, NDF_ONLY_PNBUF);
1718 vput(nd.ni_dvp);
1719 if (vp == nd.ni_dvp)
1720 vrele(vp);
1721 else
1722 vput(vp);
1723 VFS_UNLOCK_GIANT(vfslocked);
1724 return (error);
1725 }
1726
1727 /*
1728 * Reposition read/write file offset.
1729 */
1730 #ifndef _SYS_SYSPROTO_H_
1731 struct lseek_args {
1732 int fd;
1733 int pad;
1734 off_t offset;
1735 int whence;
1736 };
1737 #endif
1738 int
1739 lseek(td, uap)
1740 struct thread *td;
1741 register struct lseek_args /* {
1742 int fd;
1743 int pad;
1744 off_t offset;
1745 int whence;
1746 } */ *uap;
1747 {
1748 struct ucred *cred = td->td_ucred;
1749 struct file *fp;
1750 struct vnode *vp;
1751 struct vattr vattr;
1752 off_t offset;
1753 int error, noneg;
1754 int vfslocked;
1755
1756 if ((error = fget(td, uap->fd, &fp)) != 0)
1757 return (error);
1758 if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) {
1759 fdrop(fp, td);
1760 return (ESPIPE);
1761 }
1762 vp = fp->f_vnode;
1763 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1764 noneg = (vp->v_type != VCHR);
1765 offset = uap->offset;
1766 switch (uap->whence) {
1767 case L_INCR:
1768 if (noneg &&
1769 (fp->f_offset < 0 ||
1770 (offset > 0 && fp->f_offset > OFF_MAX - offset))) {
1771 error = EOVERFLOW;
1772 break;
1773 }
1774 offset += fp->f_offset;
1775 break;
1776 case L_XTND:
1777 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1778 error = VOP_GETATTR(vp, &vattr, cred, td);
1779 VOP_UNLOCK(vp, 0, td);
1780 if (error)
1781 break;
1782 if (noneg &&
1783 (vattr.va_size > OFF_MAX ||
1784 (offset > 0 && vattr.va_size > OFF_MAX - offset))) {
1785 error = EOVERFLOW;
1786 break;
1787 }
1788 offset += vattr.va_size;
1789 break;
1790 case L_SET:
1791 break;
1792 default:
1793 error = EINVAL;
1794 }
1795 if (error == 0 && noneg && offset < 0)
1796 error = EINVAL;
1797 if (error != 0)
1798 goto drop;
1799 fp->f_offset = offset;
1800 *(off_t *)(td->td_retval) = fp->f_offset;
1801 drop:
1802 fdrop(fp, td);
1803 VFS_UNLOCK_GIANT(vfslocked);
1804 return (error);
1805 }
1806
1807 #if defined(COMPAT_43)
1808 /*
1809 * Reposition read/write file offset.
1810 */
1811 #ifndef _SYS_SYSPROTO_H_
1812 struct olseek_args {
1813 int fd;
1814 long offset;
1815 int whence;
1816 };
1817 #endif
1818 int
1819 olseek(td, uap)
1820 struct thread *td;
1821 register struct olseek_args /* {
1822 int fd;
1823 long offset;
1824 int whence;
1825 } */ *uap;
1826 {
1827 struct lseek_args /* {
1828 int fd;
1829 int pad;
1830 off_t offset;
1831 int whence;
1832 } */ nuap;
1833 int error;
1834
1835 nuap.fd = uap->fd;
1836 nuap.offset = uap->offset;
1837 nuap.whence = uap->whence;
1838 error = lseek(td, &nuap);
1839 return (error);
1840 }
1841 #endif /* COMPAT_43 */
1842
1843 /*
1844 * Check access permissions using passed credentials.
1845 */
1846 static int
1847 vn_access(vp, user_flags, cred, td)
1848 struct vnode *vp;
1849 int user_flags;
1850 struct ucred *cred;
1851 struct thread *td;
1852 {
1853 int error, flags;
1854
1855 /* Flags == 0 means only check for existence. */
1856 error = 0;
1857 if (user_flags) {
1858 flags = 0;
1859 if (user_flags & R_OK)
1860 flags |= VREAD;
1861 if (user_flags & W_OK)
1862 flags |= VWRITE;
1863 if (user_flags & X_OK)
1864 flags |= VEXEC;
1865 #ifdef MAC
1866 error = mac_check_vnode_access(cred, vp, flags);
1867 if (error)
1868 return (error);
1869 #endif
1870 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1871 error = VOP_ACCESS(vp, flags, cred, td);
1872 }
1873 return (error);
1874 }
1875
1876 /*
1877 * Check access permissions using "real" credentials.
1878 */
1879 #ifndef _SYS_SYSPROTO_H_
1880 struct access_args {
1881 char *path;
1882 int flags;
1883 };
1884 #endif
1885 int
1886 access(td, uap)
1887 struct thread *td;
1888 register struct access_args /* {
1889 char *path;
1890 int flags;
1891 } */ *uap;
1892 {
1893
1894 return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags));
1895 }
1896
1897 int
1898 kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags)
1899 {
1900 struct ucred *cred, *tmpcred;
1901 register struct vnode *vp;
1902 struct nameidata nd;
1903 int vfslocked;
1904 int error;
1905
1906 /*
1907 * Create and modify a temporary credential instead of one that
1908 * is potentially shared. This could also mess up socket
1909 * buffer accounting which can run in an interrupt context.
1910 */
1911 cred = td->td_ucred;
1912 tmpcred = crdup(cred);
1913 tmpcred->cr_uid = cred->cr_ruid;
1914 tmpcred->cr_groups[0] = cred->cr_rgid;
1915 td->td_ucred = tmpcred;
1916 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
1917 pathseg, path, td);
1918 if ((error = namei(&nd)) != 0)
1919 goto out1;
1920 vfslocked = NDHASGIANT(&nd);
1921 vp = nd.ni_vp;
1922
1923 error = vn_access(vp, flags, tmpcred, td);
1924 NDFREE(&nd, NDF_ONLY_PNBUF);
1925 vput(vp);
1926 VFS_UNLOCK_GIANT(vfslocked);
1927 out1:
1928 td->td_ucred = cred;
1929 crfree(tmpcred);
1930 return (error);
1931 }
1932
1933 /*
1934 * Check access permissions using "effective" credentials.
1935 */
1936 #ifndef _SYS_SYSPROTO_H_
1937 struct eaccess_args {
1938 char *path;
1939 int flags;
1940 };
1941 #endif
1942 int
1943 eaccess(td, uap)
1944 struct thread *td;
1945 register struct eaccess_args /* {
1946 char *path;
1947 int flags;
1948 } */ *uap;
1949 {
1950 struct nameidata nd;
1951 struct vnode *vp;
1952 int vfslocked;
1953 int error;
1954
1955 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
1956 UIO_USERSPACE, uap->path, td);
1957 if ((error = namei(&nd)) != 0)
1958 return (error);
1959 vp = nd.ni_vp;
1960 vfslocked = NDHASGIANT(&nd);
1961 error = vn_access(vp, uap->flags, td->td_ucred, td);
1962 NDFREE(&nd, NDF_ONLY_PNBUF);
1963 vput(vp);
1964 VFS_UNLOCK_GIANT(vfslocked);
1965 return (error);
1966 }
1967
1968 #if defined(COMPAT_43)
1969 /*
1970 * Get file status; this version follows links.
1971 */
1972 #ifndef _SYS_SYSPROTO_H_
1973 struct ostat_args {
1974 char *path;
1975 struct ostat *ub;
1976 };
1977 #endif
1978 int
1979 ostat(td, uap)
1980 struct thread *td;
1981 register struct ostat_args /* {
1982 char *path;
1983 struct ostat *ub;
1984 } */ *uap;
1985 {
1986 struct stat sb;
1987 struct ostat osb;
1988 int error;
1989
1990 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1991 if (error)
1992 return (error);
1993 cvtstat(&sb, &osb);
1994 error = copyout(&osb, uap->ub, sizeof (osb));
1995 return (error);
1996 }
1997
1998 /*
1999 * Get file status; this version does not follow links.
2000 */
2001 #ifndef _SYS_SYSPROTO_H_
2002 struct olstat_args {
2003 char *path;
2004 struct ostat *ub;
2005 };
2006 #endif
2007 int
2008 olstat(td, uap)
2009 struct thread *td;
2010 register struct olstat_args /* {
2011 char *path;
2012 struct ostat *ub;
2013 } */ *uap;
2014 {
2015 struct stat sb;
2016 struct ostat osb;
2017 int error;
2018
2019 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2020 if (error)
2021 return (error);
2022 cvtstat(&sb, &osb);
2023 error = copyout(&osb, uap->ub, sizeof (osb));
2024 return (error);
2025 }
2026
2027 /*
2028 * Convert from an old to a new stat structure.
2029 */
2030 void
2031 cvtstat(st, ost)
2032 struct stat *st;
2033 struct ostat *ost;
2034 {
2035
2036 ost->st_dev = st->st_dev;
2037 ost->st_ino = st->st_ino;
2038 ost->st_mode = st->st_mode;
2039 ost->st_nlink = st->st_nlink;
2040 ost->st_uid = st->st_uid;
2041 ost->st_gid = st->st_gid;
2042 ost->st_rdev = st->st_rdev;
2043 if (st->st_size < (quad_t)1 << 32)
2044 ost->st_size = st->st_size;
2045 else
2046 ost->st_size = -2;
2047 ost->st_atime = st->st_atime;
2048 ost->st_mtime = st->st_mtime;
2049 ost->st_ctime = st->st_ctime;
2050 ost->st_blksize = st->st_blksize;
2051 ost->st_blocks = st->st_blocks;
2052 ost->st_flags = st->st_flags;
2053 ost->st_gen = st->st_gen;
2054 }
2055 #endif /* COMPAT_43 */
2056
2057 /*
2058 * Get file status; this version follows links.
2059 */
2060 #ifndef _SYS_SYSPROTO_H_
2061 struct stat_args {
2062 char *path;
2063 struct stat *ub;
2064 };
2065 #endif
2066 int
2067 stat(td, uap)
2068 struct thread *td;
2069 register struct stat_args /* {
2070 char *path;
2071 struct stat *ub;
2072 } */ *uap;
2073 {
2074 struct stat sb;
2075 int error;
2076
2077 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2078 if (error == 0)
2079 error = copyout(&sb, uap->ub, sizeof (sb));
2080 return (error);
2081 }
2082
2083 int
2084 kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
2085 {
2086 struct nameidata nd;
2087 struct stat sb;
2088 int error, vfslocked;
2089
2090 NDINIT(&nd, LOOKUP,
2091 FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | AUDITVNODE1,
2092 pathseg, path, td);
2093 if ((error = namei(&nd)) != 0)
2094 return (error);
2095 vfslocked = NDHASGIANT(&nd);
2096 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
2097 NDFREE(&nd, NDF_ONLY_PNBUF);
2098 vput(nd.ni_vp);
2099 VFS_UNLOCK_GIANT(vfslocked);
2100 if (error)
2101 return (error);
2102 *sbp = sb;
2103 return (0);
2104 }
2105
2106 /*
2107 * Get file status; this version does not follow links.
2108 */
2109 #ifndef _SYS_SYSPROTO_H_
2110 struct lstat_args {
2111 char *path;
2112 struct stat *ub;
2113 };
2114 #endif
2115 int
2116 lstat(td, uap)
2117 struct thread *td;
2118 register struct lstat_args /* {
2119 char *path;
2120 struct stat *ub;
2121 } */ *uap;
2122 {
2123 struct stat sb;
2124 int error;
2125
2126 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2127 if (error == 0)
2128 error = copyout(&sb, uap->ub, sizeof (sb));
2129 return (error);
2130 }
2131
2132 int
2133 kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
2134 {
2135 struct vnode *vp;
2136 struct stat sb;
2137 struct nameidata nd;
2138 int error, vfslocked;
2139
2140 NDINIT(&nd, LOOKUP,
2141 NOFOLLOW | LOCKLEAF | LOCKSHARED | MPSAFE | AUDITVNODE1,
2142 pathseg, path, td);
2143 if ((error = namei(&nd)) != 0)
2144 return (error);
2145 vfslocked = NDHASGIANT(&nd);
2146 vp = nd.ni_vp;
2147 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
2148 NDFREE(&nd, NDF_ONLY_PNBUF);
2149 vput(vp);
2150 VFS_UNLOCK_GIANT(vfslocked);
2151 if (error)
2152 return (error);
2153 *sbp = sb;
2154 return (0);
2155 }
2156
2157 /*
2158 * Implementation of the NetBSD [l]stat() functions.
2159 */
2160 void
2161 cvtnstat(sb, nsb)
2162 struct stat *sb;
2163 struct nstat *nsb;
2164 {
2165 bzero(nsb, sizeof *nsb);
2166 nsb->st_dev = sb->st_dev;
2167 nsb->st_ino = sb->st_ino;
2168 nsb->st_mode = sb->st_mode;
2169 nsb->st_nlink = sb->st_nlink;
2170 nsb->st_uid = sb->st_uid;
2171 nsb->st_gid = sb->st_gid;
2172 nsb->st_rdev = sb->st_rdev;
2173 nsb->st_atimespec = sb->st_atimespec;
2174 nsb->st_mtimespec = sb->st_mtimespec;
2175 nsb->st_ctimespec = sb->st_ctimespec;
2176 nsb->st_size = sb->st_size;
2177 nsb->st_blocks = sb->st_blocks;
2178 nsb->st_blksize = sb->st_blksize;
2179 nsb->st_flags = sb->st_flags;
2180 nsb->st_gen = sb->st_gen;
2181 nsb->st_birthtimespec = sb->st_birthtimespec;
2182 }
2183
2184 #ifndef _SYS_SYSPROTO_H_
2185 struct nstat_args {
2186 char *path;
2187 struct nstat *ub;
2188 };
2189 #endif
2190 int
2191 nstat(td, uap)
2192 struct thread *td;
2193 register struct nstat_args /* {
2194 char *path;
2195 struct nstat *ub;
2196 } */ *uap;
2197 {
2198 struct stat sb;
2199 struct nstat nsb;
2200 int error;
2201
2202 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2203 if (error)
2204 return (error);
2205 cvtnstat(&sb, &nsb);
2206 error = copyout(&nsb, uap->ub, sizeof (nsb));
2207 return (error);
2208 }
2209
2210 /*
2211 * NetBSD lstat. Get file status; this version does not follow links.
2212 */
2213 #ifndef _SYS_SYSPROTO_H_
2214 struct lstat_args {
2215 char *path;
2216 struct stat *ub;
2217 };
2218 #endif
2219 int
2220 nlstat(td, uap)
2221 struct thread *td;
2222 register struct nlstat_args /* {
2223 char *path;
2224 struct nstat *ub;
2225 } */ *uap;
2226 {
2227 struct stat sb;
2228 struct nstat nsb;
2229 int error;
2230
2231 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2232 if (error)
2233 return (error);
2234 cvtnstat(&sb, &nsb);
2235 error = copyout(&nsb, uap->ub, sizeof (nsb));
2236 return (error);
2237 }
2238
2239 /*
2240 * Get configurable pathname variables.
2241 */
2242 #ifndef _SYS_SYSPROTO_H_
2243 struct pathconf_args {
2244 char *path;
2245 int name;
2246 };
2247 #endif
2248 int
2249 pathconf(td, uap)
2250 struct thread *td;
2251 register struct pathconf_args /* {
2252 char *path;
2253 int name;
2254 } */ *uap;
2255 {
2256
2257 return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name));
2258 }
2259
2260 int
2261 kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name)
2262 {
2263 struct nameidata nd;
2264 int error, vfslocked;
2265
2266 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
2267 pathseg, path, td);
2268 if ((error = namei(&nd)) != 0)
2269 return (error);
2270 vfslocked = NDHASGIANT(&nd);
2271 NDFREE(&nd, NDF_ONLY_PNBUF);
2272
2273 /* If asynchronous I/O is available, it works for all files. */
2274 if (name == _PC_ASYNC_IO)
2275 td->td_retval[0] = async_io_version;
2276 else
2277 error = VOP_PATHCONF(nd.ni_vp, name, td->td_retval);
2278 vput(nd.ni_vp);
2279 VFS_UNLOCK_GIANT(vfslocked);
2280 return (error);
2281 }
2282
2283 /*
2284 * Return target name of a symbolic link.
2285 */
2286 #ifndef _SYS_SYSPROTO_H_
2287 struct readlink_args {
2288 char *path;
2289 char *buf;
2290 int count;
2291 };
2292 #endif
2293 int
2294 readlink(td, uap)
2295 struct thread *td;
2296 register struct readlink_args /* {
2297 char *path;
2298 char *buf;
2299 int count;
2300 } */ *uap;
2301 {
2302
2303 return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf,
2304 UIO_USERSPACE, uap->count));
2305 }
2306
2307 int
2308 kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf,
2309 enum uio_seg bufseg, int count)
2310 {
2311 register struct vnode *vp;
2312 struct iovec aiov;
2313 struct uio auio;
2314 int error;
2315 struct nameidata nd;
2316 int vfslocked;
2317
2318 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
2319 pathseg, path, td);
2320 if ((error = namei(&nd)) != 0)
2321 return (error);
2322 NDFREE(&nd, NDF_ONLY_PNBUF);
2323 vfslocked = NDHASGIANT(&nd);
2324 vp = nd.ni_vp;
2325 #ifdef MAC
2326 error = mac_check_vnode_readlink(td->td_ucred, vp);
2327 if (error) {
2328 vput(vp);
2329 VFS_UNLOCK_GIANT(vfslocked);
2330 return (error);
2331 }
2332 #endif
2333 if (vp->v_type != VLNK)
2334 error = EINVAL;
2335 else {
2336 aiov.iov_base = buf;
2337 aiov.iov_len = count;
2338 auio.uio_iov = &aiov;
2339 auio.uio_iovcnt = 1;
2340 auio.uio_offset = 0;
2341 auio.uio_rw = UIO_READ;
2342 auio.uio_segflg = bufseg;
2343 auio.uio_td = td;
2344 auio.uio_resid = count;
2345 error = VOP_READLINK(vp, &auio, td->td_ucred);
2346 }
2347 vput(vp);
2348 VFS_UNLOCK_GIANT(vfslocked);
2349 td->td_retval[0] = count - auio.uio_resid;
2350 return (error);
2351 }
2352
2353 /*
2354 * Common implementation code for chflags() and fchflags().
2355 */
2356 static int
2357 setfflags(td, vp, flags)
2358 struct thread *td;
2359 struct vnode *vp;
2360 int flags;
2361 {
2362 int error;
2363 struct mount *mp;
2364 struct vattr vattr;
2365
2366 /*
2367 * Prevent non-root users from setting flags on devices. When
2368 * a device is reused, users can retain ownership of the device
2369 * if they are allowed to set flags and programs assume that
2370 * chown can't fail when done as root.
2371 */
2372 if (vp->v_type == VCHR || vp->v_type == VBLK) {
2373 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
2374 if (error)
2375 return (error);
2376 }
2377
2378 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2379 return (error);
2380 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2381 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2382 VATTR_NULL(&vattr);
2383 vattr.va_flags = flags;
2384 #ifdef MAC
2385 error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags);
2386 if (error == 0)
2387 #endif
2388 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2389 VOP_UNLOCK(vp, 0, td);
2390 vn_finished_write(mp);
2391 return (error);
2392 }
2393
2394 /*
2395 * Change flags of a file given a path name.
2396 */
2397 #ifndef _SYS_SYSPROTO_H_
2398 struct chflags_args {
2399 char *path;
2400 int flags;
2401 };
2402 #endif
2403 int
2404 chflags(td, uap)
2405 struct thread *td;
2406 register struct chflags_args /* {
2407 char *path;
2408 int flags;
2409 } */ *uap;
2410 {
2411 int error;
2412 struct nameidata nd;
2413 int vfslocked;
2414
2415 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE,
2416 uap->path, td);
2417 if ((error = namei(&nd)) != 0)
2418 return (error);
2419 NDFREE(&nd, NDF_ONLY_PNBUF);
2420 vfslocked = NDHASGIANT(&nd);
2421 error = setfflags(td, nd.ni_vp, uap->flags);
2422 vrele(nd.ni_vp);
2423 VFS_UNLOCK_GIANT(vfslocked);
2424 return (error);
2425 }
2426
2427 /*
2428 * Same as chflags() but doesn't follow symlinks.
2429 */
2430 int
2431 lchflags(td, uap)
2432 struct thread *td;
2433 register struct lchflags_args /* {
2434 char *path;
2435 int flags;
2436 } */ *uap;
2437 {
2438 int error;
2439 struct nameidata nd;
2440 int vfslocked;
2441
2442 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_USERSPACE | AUDITVNODE1,
2443 uap->path, td);
2444 if ((error = namei(&nd)) != 0)
2445 return (error);
2446 vfslocked = NDHASGIANT(&nd);
2447 NDFREE(&nd, NDF_ONLY_PNBUF);
2448 error = setfflags(td, nd.ni_vp, uap->flags);
2449 vrele(nd.ni_vp);
2450 VFS_UNLOCK_GIANT(vfslocked);
2451 return (error);
2452 }
2453
2454 /*
2455 * Change flags of a file given a file descriptor.
2456 */
2457 #ifndef _SYS_SYSPROTO_H_
2458 struct fchflags_args {
2459 int fd;
2460 int flags;
2461 };
2462 #endif
2463 int
2464 fchflags(td, uap)
2465 struct thread *td;
2466 register struct fchflags_args /* {
2467 int fd;
2468 int flags;
2469 } */ *uap;
2470 {
2471 struct file *fp;
2472 int vfslocked;
2473 int error;
2474
2475 AUDIT_ARG(fd, uap->fd);
2476 AUDIT_ARG(fflags, uap->flags);
2477 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2478 return (error);
2479 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2480 #ifdef AUDIT
2481 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2482 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2483 VOP_UNLOCK(fp->f_vnode, 0, td);
2484 #endif
2485 error = setfflags(td, fp->f_vnode, uap->flags);
2486 fdrop(fp, td);
2487 VFS_UNLOCK_GIANT(vfslocked);
2488 return (error);
2489 }
2490
2491 /*
2492 * Common implementation code for chmod(), lchmod() and fchmod().
2493 */
2494 static int
2495 setfmode(td, vp, mode)
2496 struct thread *td;
2497 struct vnode *vp;
2498 int mode;
2499 {
2500 int error;
2501 struct mount *mp;
2502 struct vattr vattr;
2503
2504 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2505 return (error);
2506 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2507 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2508 VATTR_NULL(&vattr);
2509 vattr.va_mode = mode & ALLPERMS;
2510 #ifdef MAC
2511 error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode);
2512 if (error == 0)
2513 #endif
2514 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2515 VOP_UNLOCK(vp, 0, td);
2516 vn_finished_write(mp);
2517 return (error);
2518 }
2519
2520 /*
2521 * Change mode of a file given path name.
2522 */
2523 #ifndef _SYS_SYSPROTO_H_
2524 struct chmod_args {
2525 char *path;
2526 int mode;
2527 };
2528 #endif
2529 int
2530 chmod(td, uap)
2531 struct thread *td;
2532 register struct chmod_args /* {
2533 char *path;
2534 int mode;
2535 } */ *uap;
2536 {
2537
2538 return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode));
2539 }
2540
2541 int
2542 kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode)
2543 {
2544 int error;
2545 struct nameidata nd;
2546 int vfslocked;
2547
2548 AUDIT_ARG(mode, mode);
2549 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2550 if ((error = namei(&nd)) != 0)
2551 return (error);
2552 vfslocked = NDHASGIANT(&nd);
2553 NDFREE(&nd, NDF_ONLY_PNBUF);
2554 error = setfmode(td, nd.ni_vp, mode);
2555 vrele(nd.ni_vp);
2556 VFS_UNLOCK_GIANT(vfslocked);
2557 return (error);
2558 }
2559
2560 /*
2561 * Change mode of a file given path name (don't follow links.)
2562 */
2563 #ifndef _SYS_SYSPROTO_H_
2564 struct lchmod_args {
2565 char *path;
2566 int mode;
2567 };
2568 #endif
2569 int
2570 lchmod(td, uap)
2571 struct thread *td;
2572 register struct lchmod_args /* {
2573 char *path;
2574 int mode;
2575 } */ *uap;
2576 {
2577 int error;
2578 struct nameidata nd;
2579 int vfslocked;
2580
2581 AUDIT_ARG(mode, (mode_t)uap->mode);
2582 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE,
2583 uap->path, td);
2584 if ((error = namei(&nd)) != 0)
2585 return (error);
2586 vfslocked = NDHASGIANT(&nd);
2587 NDFREE(&nd, NDF_ONLY_PNBUF);
2588 error = setfmode(td, nd.ni_vp, uap->mode);
2589 vrele(nd.ni_vp);
2590 VFS_UNLOCK_GIANT(vfslocked);
2591 return (error);
2592 }
2593
2594 /*
2595 * Change mode of a file given a file descriptor.
2596 */
2597 #ifndef _SYS_SYSPROTO_H_
2598 struct fchmod_args {
2599 int fd;
2600 int mode;
2601 };
2602 #endif
2603 int
2604 fchmod(td, uap)
2605 struct thread *td;
2606 register struct fchmod_args /* {
2607 int fd;
2608 int mode;
2609 } */ *uap;
2610 {
2611 struct file *fp;
2612 int vfslocked;
2613 int error;
2614
2615 AUDIT_ARG(fd, uap->fd);
2616 AUDIT_ARG(mode, uap->mode);
2617 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2618 return (error);
2619 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2620 #ifdef AUDIT
2621 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2622 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2623 VOP_UNLOCK(fp->f_vnode, 0, td);
2624 #endif
2625 error = setfmode(td, fp->f_vnode, uap->mode);
2626 fdrop(fp, td);
2627 VFS_UNLOCK_GIANT(vfslocked);
2628 return (error);
2629 }
2630
2631 /*
2632 * Common implementation for chown(), lchown(), and fchown()
2633 */
2634 static int
2635 setfown(td, vp, uid, gid)
2636 struct thread *td;
2637 struct vnode *vp;
2638 uid_t uid;
2639 gid_t gid;
2640 {
2641 int error;
2642 struct mount *mp;
2643 struct vattr vattr;
2644
2645 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2646 return (error);
2647 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2648 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2649 VATTR_NULL(&vattr);
2650 vattr.va_uid = uid;
2651 vattr.va_gid = gid;
2652 #ifdef MAC
2653 error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid,
2654 vattr.va_gid);
2655 if (error == 0)
2656 #endif
2657 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2658 VOP_UNLOCK(vp, 0, td);
2659 vn_finished_write(mp);
2660 return (error);
2661 }
2662
2663 /*
2664 * Set ownership given a path name.
2665 */
2666 #ifndef _SYS_SYSPROTO_H_
2667 struct chown_args {
2668 char *path;
2669 int uid;
2670 int gid;
2671 };
2672 #endif
2673 int
2674 chown(td, uap)
2675 struct thread *td;
2676 register struct chown_args /* {
2677 char *path;
2678 int uid;
2679 int gid;
2680 } */ *uap;
2681 {
2682
2683 return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2684 }
2685
2686 int
2687 kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2688 int gid)
2689 {
2690 int error;
2691 struct nameidata nd;
2692 int vfslocked;
2693
2694 AUDIT_ARG(owner, uid, gid);
2695 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path,
2696 td);
2697 if ((error = namei(&nd)) != 0)
2698 return (error);
2699 vfslocked = NDHASGIANT(&nd);
2700 NDFREE(&nd, NDF_ONLY_PNBUF);
2701 error = setfown(td, nd.ni_vp, uid, gid);
2702 vrele(nd.ni_vp);
2703 VFS_UNLOCK_GIANT(vfslocked);
2704 return (error);
2705 }
2706
2707 /*
2708 * Set ownership given a path name, do not cross symlinks.
2709 */
2710 #ifndef _SYS_SYSPROTO_H_
2711 struct lchown_args {
2712 char *path;
2713 int uid;
2714 int gid;
2715 };
2716 #endif
2717 int
2718 lchown(td, uap)
2719 struct thread *td;
2720 register struct lchown_args /* {
2721 char *path;
2722 int uid;
2723 int gid;
2724 } */ *uap;
2725 {
2726
2727 return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2728 }
2729
2730 int
2731 kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2732 int gid)
2733 {
2734 int error;
2735 struct nameidata nd;
2736 int vfslocked;
2737
2738 AUDIT_ARG(owner, uid, gid);
2739 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path,
2740 td);
2741 if ((error = namei(&nd)) != 0)
2742 return (error);
2743 vfslocked = NDHASGIANT(&nd);
2744 NDFREE(&nd, NDF_ONLY_PNBUF);
2745 error = setfown(td, nd.ni_vp, uid, gid);
2746 vrele(nd.ni_vp);
2747 VFS_UNLOCK_GIANT(vfslocked);
2748 return (error);
2749 }
2750
2751 /*
2752 * Set ownership given a file descriptor.
2753 */
2754 #ifndef _SYS_SYSPROTO_H_
2755 struct fchown_args {
2756 int fd;
2757 int uid;
2758 int gid;
2759 };
2760 #endif
2761 int
2762 fchown(td, uap)
2763 struct thread *td;
2764 register struct fchown_args /* {
2765 int fd;
2766 int uid;
2767 int gid;
2768 } */ *uap;
2769 {
2770 struct file *fp;
2771 int vfslocked;
2772 int error;
2773
2774 AUDIT_ARG(fd, uap->fd);
2775 AUDIT_ARG(owner, uap->uid, uap->gid);
2776 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2777 return (error);
2778 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2779 #ifdef AUDIT
2780 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2781 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2782 VOP_UNLOCK(fp->f_vnode, 0, td);
2783 #endif
2784 error = setfown(td, fp->f_vnode, uap->uid, uap->gid);
2785 fdrop(fp, td);
2786 VFS_UNLOCK_GIANT(vfslocked);
2787 return (error);
2788 }
2789
2790 /*
2791 * Common implementation code for utimes(), lutimes(), and futimes().
2792 */
2793 static int
2794 getutimes(usrtvp, tvpseg, tsp)
2795 const struct timeval *usrtvp;
2796 enum uio_seg tvpseg;
2797 struct timespec *tsp;
2798 {
2799 struct timeval tv[2];
2800 const struct timeval *tvp;
2801 int error;
2802
2803 if (usrtvp == NULL) {
2804 microtime(&tv[0]);
2805 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2806 tsp[1] = tsp[0];
2807 } else {
2808 if (tvpseg == UIO_SYSSPACE) {
2809 tvp = usrtvp;
2810 } else {
2811 if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0)
2812 return (error);
2813 tvp = tv;
2814 }
2815
2816 if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 ||
2817 tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
2818 return (EINVAL);
2819 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
2820 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
2821 }
2822 return (0);
2823 }
2824
2825 /*
2826 * Common implementation code for utimes(), lutimes(), and futimes().
2827 */
2828 static int
2829 setutimes(td, vp, ts, numtimes, nullflag)
2830 struct thread *td;
2831 struct vnode *vp;
2832 const struct timespec *ts;
2833 int numtimes;
2834 int nullflag;
2835 {
2836 int error, setbirthtime;
2837 struct mount *mp;
2838 struct vattr vattr;
2839
2840 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2841 return (error);
2842 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2843 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2844 setbirthtime = 0;
2845 if (numtimes < 3 && VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 &&
2846 timespeccmp(&ts[1], &vattr.va_birthtime, < ))
2847 setbirthtime = 1;
2848 VATTR_NULL(&vattr);
2849 vattr.va_atime = ts[0];
2850 vattr.va_mtime = ts[1];
2851 if (setbirthtime)
2852 vattr.va_birthtime = ts[1];
2853 if (numtimes > 2)
2854 vattr.va_birthtime = ts[2];
2855 if (nullflag)
2856 vattr.va_vaflags |= VA_UTIMES_NULL;
2857 #ifdef MAC
2858 error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime,
2859 vattr.va_mtime);
2860 #endif
2861 if (error == 0)
2862 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2863 VOP_UNLOCK(vp, 0, td);
2864 vn_finished_write(mp);
2865 return (error);
2866 }
2867
2868 /*
2869 * Set the access and modification times of a file.
2870 */
2871 #ifndef _SYS_SYSPROTO_H_
2872 struct utimes_args {
2873 char *path;
2874 struct timeval *tptr;
2875 };
2876 #endif
2877 int
2878 utimes(td, uap)
2879 struct thread *td;
2880 register struct utimes_args /* {
2881 char *path;
2882 struct timeval *tptr;
2883 } */ *uap;
2884 {
2885
2886 return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2887 UIO_USERSPACE));
2888 }
2889
2890 int
2891 kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
2892 struct timeval *tptr, enum uio_seg tptrseg)
2893 {
2894 struct timespec ts[2];
2895 int error;
2896 struct nameidata nd;
2897 int vfslocked;
2898
2899 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2900 return (error);
2901 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2902 if ((error = namei(&nd)) != 0)
2903 return (error);
2904 vfslocked = NDHASGIANT(&nd);
2905 NDFREE(&nd, NDF_ONLY_PNBUF);
2906 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2907 vrele(nd.ni_vp);
2908 VFS_UNLOCK_GIANT(vfslocked);
2909 return (error);
2910 }
2911
2912 /*
2913 * Set the access and modification times of a file.
2914 */
2915 #ifndef _SYS_SYSPROTO_H_
2916 struct lutimes_args {
2917 char *path;
2918 struct timeval *tptr;
2919 };
2920 #endif
2921 int
2922 lutimes(td, uap)
2923 struct thread *td;
2924 register struct lutimes_args /* {
2925 char *path;
2926 struct timeval *tptr;
2927 } */ *uap;
2928 {
2929
2930 return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2931 UIO_USERSPACE));
2932 }
2933
2934 int
2935 kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg,
2936 struct timeval *tptr, enum uio_seg tptrseg)
2937 {
2938 struct timespec ts[2];
2939 int error;
2940 struct nameidata nd;
2941 int vfslocked;
2942
2943 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2944 return (error);
2945 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2946 if ((error = namei(&nd)) != 0)
2947 return (error);
2948 vfslocked = NDHASGIANT(&nd);
2949 NDFREE(&nd, NDF_ONLY_PNBUF);
2950 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2951 vrele(nd.ni_vp);
2952 VFS_UNLOCK_GIANT(vfslocked);
2953 return (error);
2954 }
2955
2956 /*
2957 * Set the access and modification times of a file.
2958 */
2959 #ifndef _SYS_SYSPROTO_H_
2960 struct futimes_args {
2961 int fd;
2962 struct timeval *tptr;
2963 };
2964 #endif
2965 int
2966 futimes(td, uap)
2967 struct thread *td;
2968 register struct futimes_args /* {
2969 int fd;
2970 struct timeval *tptr;
2971 } */ *uap;
2972 {
2973
2974 return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE));
2975 }
2976
2977 int
2978 kern_futimes(struct thread *td, int fd, struct timeval *tptr,
2979 enum uio_seg tptrseg)
2980 {
2981 struct timespec ts[2];
2982 struct file *fp;
2983 int vfslocked;
2984 int error;
2985
2986 AUDIT_ARG(fd, fd);
2987 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2988 return (error);
2989 if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
2990 return (error);
2991 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2992 #ifdef AUDIT
2993 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2994 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2995 VOP_UNLOCK(fp->f_vnode, 0, td);
2996 #endif
2997 error = setutimes(td, fp->f_vnode, ts, 2, tptr == NULL);
2998 fdrop(fp, td);
2999 VFS_UNLOCK_GIANT(vfslocked);
3000 return (error);
3001 }
3002
3003 /*
3004 * Truncate a file given its path name.
3005 */
3006 #ifndef _SYS_SYSPROTO_H_
3007 struct truncate_args {
3008 char *path;
3009 int pad;
3010 off_t length;
3011 };
3012 #endif
3013 int
3014 truncate(td, uap)
3015 struct thread *td;
3016 register struct truncate_args /* {
3017 char *path;
3018 int pad;
3019 off_t length;
3020 } */ *uap;
3021 {
3022
3023 return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
3024 }
3025
3026 int
3027 kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length)
3028 {
3029 struct mount *mp;
3030 struct vnode *vp;
3031 struct vattr vattr;
3032 int error;
3033 struct nameidata nd;
3034 int vfslocked;
3035
3036 if (length < 0)
3037 return(EINVAL);
3038 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
3039 if ((error = namei(&nd)) != 0)
3040 return (error);
3041 vfslocked = NDHASGIANT(&nd);
3042 vp = nd.ni_vp;
3043 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
3044 vrele(vp);
3045 VFS_UNLOCK_GIANT(vfslocked);
3046 return (error);
3047 }
3048 NDFREE(&nd, NDF_ONLY_PNBUF);
3049 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3050 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3051 if (vp->v_type == VDIR)
3052 error = EISDIR;
3053 #ifdef MAC
3054 else if ((error = mac_check_vnode_write(td->td_ucred, NOCRED, vp))) {
3055 }
3056 #endif
3057 else if ((error = vn_writechk(vp)) == 0 &&
3058 (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
3059 VATTR_NULL(&vattr);
3060 vattr.va_size = length;
3061 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
3062 }
3063 vput(vp);
3064 vn_finished_write(mp);
3065 VFS_UNLOCK_GIANT(vfslocked);
3066 return (error);
3067 }
3068
3069 /*
3070 * Truncate a file given a file descriptor.
3071 */
3072 #ifndef _SYS_SYSPROTO_H_
3073 struct ftruncate_args {
3074 int fd;
3075 int pad;
3076 off_t length;
3077 };
3078 #endif
3079 int
3080 ftruncate(td, uap)
3081 struct thread *td;
3082 register struct ftruncate_args /* {
3083 int fd;
3084 int pad;
3085 off_t length;
3086 } */ *uap;
3087 {
3088 struct mount *mp;
3089 struct vattr vattr;
3090 struct vnode *vp;
3091 struct file *fp;
3092 int vfslocked;
3093 int error;
3094
3095 AUDIT_ARG(fd, uap->fd);
3096 if (uap->length < 0)
3097 return(EINVAL);
3098 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3099 return (error);
3100 if ((fp->f_flag & FWRITE) == 0) {
3101 fdrop(fp, td);
3102 return (EINVAL);
3103 }
3104 vp = fp->f_vnode;
3105 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3106 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3107 goto drop;
3108 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3109 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3110 AUDIT_ARG(vnode, vp, ARG_VNODE1);
3111 if (vp->v_type == VDIR)
3112 error = EISDIR;
3113 #ifdef MAC
3114 else if ((error = mac_check_vnode_write(td->td_ucred, fp->f_cred,
3115 vp))) {
3116 }
3117 #endif
3118 else if ((error = vn_writechk(vp)) == 0) {
3119 VATTR_NULL(&vattr);
3120 vattr.va_size = uap->length;
3121 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
3122 }
3123 VOP_UNLOCK(vp, 0, td);
3124 vn_finished_write(mp);
3125 drop:
3126 VFS_UNLOCK_GIANT(vfslocked);
3127 fdrop(fp, td);
3128 return (error);
3129 }
3130
3131 #if defined(COMPAT_43)
3132 /*
3133 * Truncate a file given its path name.
3134 */
3135 #ifndef _SYS_SYSPROTO_H_
3136 struct otruncate_args {
3137 char *path;
3138 long length;
3139 };
3140 #endif
3141 int
3142 otruncate(td, uap)
3143 struct thread *td;
3144 register struct otruncate_args /* {
3145 char *path;
3146 long length;
3147 } */ *uap;
3148 {
3149 struct truncate_args /* {
3150 char *path;
3151 int pad;
3152 off_t length;
3153 } */ nuap;
3154
3155 nuap.path = uap->path;
3156 nuap.length = uap->length;
3157 return (truncate(td, &nuap));
3158 }
3159
3160 /*
3161 * Truncate a file given a file descriptor.
3162 */
3163 #ifndef _SYS_SYSPROTO_H_
3164 struct oftruncate_args {
3165 int fd;
3166 long length;
3167 };
3168 #endif
3169 int
3170 oftruncate(td, uap)
3171 struct thread *td;
3172 register struct oftruncate_args /* {
3173 int fd;
3174 long length;
3175 } */ *uap;
3176 {
3177 struct ftruncate_args /* {
3178 int fd;
3179 int pad;
3180 off_t length;
3181 } */ nuap;
3182
3183 nuap.fd = uap->fd;
3184 nuap.length = uap->length;
3185 return (ftruncate(td, &nuap));
3186 }
3187 #endif /* COMPAT_43 */
3188
3189 /*
3190 * Sync an open file.
3191 */
3192 #ifndef _SYS_SYSPROTO_H_
3193 struct fsync_args {
3194 int fd;
3195 };
3196 #endif
3197 int
3198 fsync(td, uap)
3199 struct thread *td;
3200 struct fsync_args /* {
3201 int fd;
3202 } */ *uap;
3203 {
3204 struct vnode *vp;
3205 struct mount *mp;
3206 struct file *fp;
3207 int vfslocked;
3208 int error;
3209
3210 AUDIT_ARG(fd, uap->fd);
3211 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3212 return (error);
3213 vp = fp->f_vnode;
3214 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3215 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3216 goto drop;
3217 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3218 AUDIT_ARG(vnode, vp, ARG_VNODE1);
3219 if (vp->v_object != NULL) {
3220 VM_OBJECT_LOCK(vp->v_object);
3221 vm_object_page_clean(vp->v_object, 0, 0, 0);
3222 VM_OBJECT_UNLOCK(vp->v_object);
3223 }
3224 error = VOP_FSYNC(vp, MNT_WAIT, td);
3225
3226 VOP_UNLOCK(vp, 0, td);
3227 vn_finished_write(mp);
3228 drop:
3229 VFS_UNLOCK_GIANT(vfslocked);
3230 fdrop(fp, td);
3231 return (error);
3232 }
3233
3234 /*
3235 * Rename files. Source and destination must either both be directories,
3236 * or both not be directories. If target is a directory, it must be empty.
3237 */
3238 #ifndef _SYS_SYSPROTO_H_
3239 struct rename_args {
3240 char *from;
3241 char *to;
3242 };
3243 #endif
3244 int
3245 rename(td, uap)
3246 struct thread *td;
3247 register struct rename_args /* {
3248 char *from;
3249 char *to;
3250 } */ *uap;
3251 {
3252
3253 return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE));
3254 }
3255
3256 int
3257 kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg)
3258 {
3259 struct mount *mp = NULL;
3260 struct vnode *tvp, *fvp, *tdvp;
3261 struct nameidata fromnd, tond;
3262 int tvfslocked;
3263 int fvfslocked;
3264 int error;
3265
3266 bwillwrite();
3267 #ifdef MAC
3268 NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE |
3269 AUDITVNODE1, pathseg, from, td);
3270 #else
3271 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE |
3272 AUDITVNODE1, pathseg, from, td);
3273 #endif
3274 if ((error = namei(&fromnd)) != 0)
3275 return (error);
3276 fvfslocked = NDHASGIANT(&fromnd);
3277 tvfslocked = 0;
3278 #ifdef MAC
3279 error = mac_check_vnode_rename_from(td->td_ucred, fromnd.ni_dvp,
3280 fromnd.ni_vp, &fromnd.ni_cnd);
3281 VOP_UNLOCK(fromnd.ni_dvp, 0, td);
3282 if (fromnd.ni_dvp != fromnd.ni_vp)
3283 VOP_UNLOCK(fromnd.ni_vp, 0, td);
3284 #endif
3285 fvp = fromnd.ni_vp;
3286 if (error == 0)
3287 error = vn_start_write(fvp, &mp, V_WAIT | PCATCH);
3288 if (error != 0) {
3289 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3290 vrele(fromnd.ni_dvp);
3291 vrele(fvp);
3292 goto out1;
3293 }
3294 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART |
3295 MPSAFE | AUDITVNODE2, pathseg, to, td);
3296 if (fromnd.ni_vp->v_type == VDIR)
3297 tond.ni_cnd.cn_flags |= WILLBEDIR;
3298 if ((error = namei(&tond)) != 0) {
3299 /* Translate error code for rename("dir1", "dir2/."). */
3300 if (error == EISDIR && fvp->v_type == VDIR)
3301 error = EINVAL;
3302 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3303 vrele(fromnd.ni_dvp);
3304 vrele(fvp);
3305 vn_finished_write(mp);
3306 goto out1;
3307 }
3308 tvfslocked = NDHASGIANT(&tond);
3309 tdvp = tond.ni_dvp;
3310 tvp = tond.ni_vp;
3311 if (tvp != NULL) {
3312 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3313 error = ENOTDIR;
3314 goto out;
3315 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3316 error = EISDIR;
3317 goto out;
3318 }
3319 }
3320 if (fvp == tdvp)
3321 error = EINVAL;
3322 /*
3323 * If the source is the same as the destination (that is, if they
3324 * are links to the same vnode), then there is nothing to do.
3325 */
3326 if (fvp == tvp)
3327 error = -1;
3328 #ifdef MAC
3329 else
3330 error = mac_check_vnode_rename_to(td->td_ucred, tdvp,
3331 tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd);
3332 #endif
3333 out:
3334 if (!error) {
3335 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
3336 if (fromnd.ni_dvp != tdvp) {
3337 VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3338 }
3339 if (tvp) {
3340 VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
3341 }
3342 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3343 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3344 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3345 NDFREE(&tond, NDF_ONLY_PNBUF);
3346 } else {
3347 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3348 NDFREE(&tond, NDF_ONLY_PNBUF);
3349 if (tvp)
3350 vput(tvp);
3351 if (tdvp == tvp)
3352 vrele(tdvp);
3353 else
3354 vput(tdvp);
3355 vrele(fromnd.ni_dvp);
3356 vrele(fvp);
3357 }
3358 vrele(tond.ni_startdir);
3359 vn_finished_write(mp);
3360 out1:
3361 if (fromnd.ni_startdir)
3362 vrele(fromnd.ni_startdir);
3363 VFS_UNLOCK_GIANT(fvfslocked);
3364 VFS_UNLOCK_GIANT(tvfslocked);
3365 if (error == -1)
3366 return (0);
3367 return (error);
3368 }
3369
3370 /*
3371 * Make a directory file.
3372 */
3373 #ifndef _SYS_SYSPROTO_H_
3374 struct mkdir_args {
3375 char *path;
3376 int mode;
3377 };
3378 #endif
3379 int
3380 mkdir(td, uap)
3381 struct thread *td;
3382 register struct mkdir_args /* {
3383 char *path;
3384 int mode;
3385 } */ *uap;
3386 {
3387
3388 return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode));
3389 }
3390
3391 int
3392 kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode)
3393 {
3394 struct mount *mp;
3395 struct vnode *vp;
3396 struct vattr vattr;
3397 int error;
3398 struct nameidata nd;
3399 int vfslocked;
3400
3401 AUDIT_ARG(mode, mode);
3402 restart:
3403 bwillwrite();
3404 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
3405 segflg, path, td);
3406 nd.ni_cnd.cn_flags |= WILLBEDIR;
3407 if ((error = namei(&nd)) != 0)
3408 return (error);
3409 vfslocked = NDHASGIANT(&nd);
3410 vp = nd.ni_vp;
3411 if (vp != NULL) {
3412 NDFREE(&nd, NDF_ONLY_PNBUF);
3413 /*
3414 * XXX namei called with LOCKPARENT but not LOCKLEAF has
3415 * the strange behaviour of leaving the vnode unlocked
3416 * if the target is the same vnode as the parent.
3417 */
3418 if (vp == nd.ni_dvp)
3419 vrele(nd.ni_dvp);
3420 else
3421 vput(nd.ni_dvp);
3422 vrele(vp);
3423 VFS_UNLOCK_GIANT(vfslocked);
3424 return (EEXIST);
3425 }
3426 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3427 NDFREE(&nd, NDF_ONLY_PNBUF);
3428 vput(nd.ni_dvp);
3429 VFS_UNLOCK_GIANT(vfslocked);
3430 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3431 return (error);
3432 goto restart;
3433 }
3434 VATTR_NULL(&vattr);
3435 vattr.va_type = VDIR;
3436 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
3437 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
3438 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
3439 #ifdef MAC
3440 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
3441 &vattr);
3442 if (error)
3443 goto out;
3444 #endif
3445 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3446 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3447 #ifdef MAC
3448 out:
3449 #endif
3450 NDFREE(&nd, NDF_ONLY_PNBUF);
3451 vput(nd.ni_dvp);
3452 if (!error)
3453 vput(nd.ni_vp);
3454 vn_finished_write(mp);
3455 VFS_UNLOCK_GIANT(vfslocked);
3456 return (error);
3457 }
3458
3459 /*
3460 * Remove a directory file.
3461 */
3462 #ifndef _SYS_SYSPROTO_H_
3463 struct rmdir_args {
3464 char *path;
3465 };
3466 #endif
3467 int
3468 rmdir(td, uap)
3469 struct thread *td;
3470 struct rmdir_args /* {
3471 char *path;
3472 } */ *uap;
3473 {
3474
3475 return (kern_rmdir(td, uap->path, UIO_USERSPACE));
3476 }
3477
3478 int
3479 kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg)
3480 {
3481 struct mount *mp;
3482 struct vnode *vp;
3483 int error;
3484 struct nameidata nd;
3485 int vfslocked;
3486
3487 restart:
3488 bwillwrite();
3489 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1,
3490 pathseg, path, td);
3491 if ((error = namei(&nd)) != 0)
3492 return (error);
3493 vfslocked = NDHASGIANT(&nd);
3494 vp = nd.ni_vp;
3495 if (vp->v_type != VDIR) {
3496 error = ENOTDIR;
3497 goto out;
3498 }
3499 /*
3500 * No rmdir "." please.
3501 */
3502 if (nd.ni_dvp == vp) {
3503 error = EINVAL;
3504 goto out;
3505 }
3506 /*
3507 * The root of a mounted filesystem cannot be deleted.
3508 */
3509 if (vp->v_vflag & VV_ROOT) {
3510 error = EBUSY;
3511 goto out;
3512 }
3513 #ifdef MAC
3514 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
3515 &nd.ni_cnd);
3516 if (error)
3517 goto out;
3518 #endif
3519 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3520 NDFREE(&nd, NDF_ONLY_PNBUF);
3521 vput(vp);
3522 if (nd.ni_dvp == vp)
3523 vrele(nd.ni_dvp);
3524 else
3525 vput(nd.ni_dvp);
3526 VFS_UNLOCK_GIANT(vfslocked);
3527 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3528 return (error);
3529 goto restart;
3530 }
3531 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3532 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3533 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3534 vn_finished_write(mp);
3535 out:
3536 NDFREE(&nd, NDF_ONLY_PNBUF);
3537 vput(vp);
3538 if (nd.ni_dvp == vp)
3539 vrele(nd.ni_dvp);
3540 else
3541 vput(nd.ni_dvp);
3542 VFS_UNLOCK_GIANT(vfslocked);
3543 return (error);
3544 }
3545
3546 #ifdef COMPAT_43
3547 /*
3548 * Read a block of directory entries in a filesystem independent format.
3549 */
3550 #ifndef _SYS_SYSPROTO_H_
3551 struct ogetdirentries_args {
3552 int fd;
3553 char *buf;
3554 u_int count;
3555 long *basep;
3556 };
3557 #endif
3558 int
3559 ogetdirentries(td, uap)
3560 struct thread *td;
3561 register struct ogetdirentries_args /* {
3562 int fd;
3563 char *buf;
3564 u_int count;
3565 long *basep;
3566 } */ *uap;
3567 {
3568 struct vnode *vp;
3569 struct file *fp;
3570 struct uio auio, kuio;
3571 struct iovec aiov, kiov;
3572 struct dirent *dp, *edp;
3573 caddr_t dirbuf;
3574 int error, eofflag, readcnt;
3575 long loff;
3576
3577 /* XXX arbitrary sanity limit on `count'. */
3578 if (uap->count > 64 * 1024)
3579 return (EINVAL);
3580 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3581 return (error);
3582 if ((fp->f_flag & FREAD) == 0) {
3583 fdrop(fp, td);
3584 return (EBADF);
3585 }
3586 vp = fp->f_vnode;
3587 unionread:
3588 if (vp->v_type != VDIR) {
3589 fdrop(fp, td);
3590 return (EINVAL);
3591 }
3592 aiov.iov_base = uap->buf;
3593 aiov.iov_len = uap->count;
3594 auio.uio_iov = &aiov;
3595 auio.uio_iovcnt = 1;
3596 auio.uio_rw = UIO_READ;
3597 auio.uio_segflg = UIO_USERSPACE;
3598 auio.uio_td = td;
3599 auio.uio_resid = uap->count;
3600 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3601 loff = auio.uio_offset = fp->f_offset;
3602 #ifdef MAC
3603 error = mac_check_vnode_readdir(td->td_ucred, vp);
3604 if (error) {
3605 VOP_UNLOCK(vp, 0, td);
3606 fdrop(fp, td);
3607 return (error);
3608 }
3609 #endif
3610 # if (BYTE_ORDER != LITTLE_ENDIAN)
3611 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3612 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
3613 NULL, NULL);
3614 fp->f_offset = auio.uio_offset;
3615 } else
3616 # endif
3617 {
3618 kuio = auio;
3619 kuio.uio_iov = &kiov;
3620 kuio.uio_segflg = UIO_SYSSPACE;
3621 kiov.iov_len = uap->count;
3622 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
3623 kiov.iov_base = dirbuf;
3624 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
3625 NULL, NULL);
3626 fp->f_offset = kuio.uio_offset;
3627 if (error == 0) {
3628 readcnt = uap->count - kuio.uio_resid;
3629 edp = (struct dirent *)&dirbuf[readcnt];
3630 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3631 # if (BYTE_ORDER == LITTLE_ENDIAN)
3632 /*
3633 * The expected low byte of
3634 * dp->d_namlen is our dp->d_type.
3635 * The high MBZ byte of dp->d_namlen
3636 * is our dp->d_namlen.
3637 */
3638 dp->d_type = dp->d_namlen;
3639 dp->d_namlen = 0;
3640 # else
3641 /*
3642 * The dp->d_type is the high byte
3643 * of the expected dp->d_namlen,
3644 * so must be zero'ed.
3645 */
3646 dp->d_type = 0;
3647 # endif
3648 if (dp->d_reclen > 0) {
3649 dp = (struct dirent *)
3650 ((char *)dp + dp->d_reclen);
3651 } else {
3652 error = EIO;
3653 break;
3654 }
3655 }
3656 if (dp >= edp)
3657 error = uiomove(dirbuf, readcnt, &auio);
3658 }
3659 FREE(dirbuf, M_TEMP);
3660 }
3661 VOP_UNLOCK(vp, 0, td);
3662 if (error) {
3663 fdrop(fp, td);
3664 return (error);
3665 }
3666 if (uap->count == auio.uio_resid) {
3667 if (union_dircheckp) {
3668 error = union_dircheckp(td, &vp, fp);
3669 if (error == -1)
3670 goto unionread;
3671 if (error) {
3672 fdrop(fp, td);
3673 return (error);
3674 }
3675 }
3676 /*
3677 * XXX We could delay dropping the lock above but
3678 * union_dircheckp complicates things.
3679 */
3680 vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, td);
3681 if ((vp->v_vflag & VV_ROOT) &&
3682 (vp->v_mount->mnt_flag & MNT_UNION)) {
3683 struct vnode *tvp = vp;
3684 vp = vp->v_mount->mnt_vnodecovered;
3685 VREF(vp);
3686 fp->f_vnode = vp;
3687 fp->f_data = vp;
3688 fp->f_offset = 0;
3689 vput(tvp);
3690 goto unionread;
3691 }
3692 VOP_UNLOCK(vp, 0, td);
3693 }
3694 error = copyout(&loff, uap->basep, sizeof(long));
3695 fdrop(fp, td);
3696 td->td_retval[0] = uap->count - auio.uio_resid;
3697 return (error);
3698 }
3699 #endif /* COMPAT_43 */
3700
3701 /*
3702 * Read a block of directory entries in a filesystem independent format.
3703 */
3704 #ifndef _SYS_SYSPROTO_H_
3705 struct getdirentries_args {
3706 int fd;
3707 char *buf;
3708 u_int count;
3709 long *basep;
3710 };
3711 #endif
3712 int
3713 getdirentries(td, uap)
3714 struct thread *td;
3715 register struct getdirentries_args /* {
3716 int fd;
3717 char *buf;
3718 u_int count;
3719 long *basep;
3720 } */ *uap;
3721 {
3722 struct vnode *vp;
3723 struct file *fp;
3724 struct uio auio;
3725 struct iovec aiov;
3726 int vfslocked;
3727 long loff;
3728 int error, eofflag;
3729
3730 AUDIT_ARG(fd, uap->fd);
3731 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3732 return (error);
3733 if ((fp->f_flag & FREAD) == 0) {
3734 fdrop(fp, td);
3735 return (EBADF);
3736 }
3737 vp = fp->f_vnode;
3738 unionread:
3739 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3740 if (vp->v_type != VDIR) {
3741 error = EINVAL;
3742 goto fail;
3743 }
3744 aiov.iov_base = uap->buf;
3745 aiov.iov_len = uap->count;
3746 auio.uio_iov = &aiov;
3747 auio.uio_iovcnt = 1;
3748 auio.uio_rw = UIO_READ;
3749 auio.uio_segflg = UIO_USERSPACE;
3750 auio.uio_td = td;
3751 auio.uio_resid = uap->count;
3752 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
3753 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3754 AUDIT_ARG(vnode, vp, ARG_VNODE1);
3755 loff = auio.uio_offset = fp->f_offset;
3756 #ifdef MAC
3757 error = mac_check_vnode_readdir(td->td_ucred, vp);
3758 if (error == 0)
3759 #endif
3760 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL,
3761 NULL);
3762 fp->f_offset = auio.uio_offset;
3763 VOP_UNLOCK(vp, 0, td);
3764 if (error)
3765 goto fail;
3766 if (uap->count == auio.uio_resid) {
3767 if (union_dircheckp) {
3768 error = union_dircheckp(td, &vp, fp);
3769 if (error == -1) {
3770 VFS_UNLOCK_GIANT(vfslocked);
3771 goto unionread;
3772 }
3773 if (error)
3774 goto fail;
3775 }
3776 /*
3777 * XXX We could delay dropping the lock above but
3778 * union_dircheckp complicates things.
3779 */
3780 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3781 if ((vp->v_vflag & VV_ROOT) &&
3782 (vp->v_mount->mnt_flag & MNT_UNION)) {
3783 struct vnode *tvp = vp;
3784 vp = vp->v_mount->mnt_vnodecovered;
3785 VREF(vp);
3786 fp->f_vnode = vp;
3787 fp->f_data = vp;
3788 fp->f_offset = 0;
3789 vput(tvp);
3790 VFS_UNLOCK_GIANT(vfslocked);
3791 goto unionread;
3792 }
3793 VOP_UNLOCK(vp, 0, td);
3794 }
3795 if (uap->basep != NULL) {
3796 error = copyout(&loff, uap->basep, sizeof(long));
3797 }
3798 td->td_retval[0] = uap->count - auio.uio_resid;
3799 fail:
3800 VFS_UNLOCK_GIANT(vfslocked);
3801 fdrop(fp, td);
3802 return (error);
3803 }
3804 #ifndef _SYS_SYSPROTO_H_
3805 struct getdents_args {
3806 int fd;
3807 char *buf;
3808 size_t count;
3809 };
3810 #endif
3811 int
3812 getdents(td, uap)
3813 struct thread *td;
3814 register struct getdents_args /* {
3815 int fd;
3816 char *buf;
3817 u_int count;
3818 } */ *uap;
3819 {
3820 struct getdirentries_args ap;
3821 ap.fd = uap->fd;
3822 ap.buf = uap->buf;
3823 ap.count = uap->count;
3824 ap.basep = NULL;
3825 return (getdirentries(td, &ap));
3826 }
3827
3828 /*
3829 * Set the mode mask for creation of filesystem nodes.
3830 *
3831 * MP SAFE
3832 */
3833 #ifndef _SYS_SYSPROTO_H_
3834 struct umask_args {
3835 int newmask;
3836 };
3837 #endif
3838 int
3839 umask(td, uap)
3840 struct thread *td;
3841 struct umask_args /* {
3842 int newmask;
3843 } */ *uap;
3844 {
3845 register struct filedesc *fdp;
3846
3847 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
3848 fdp = td->td_proc->p_fd;
3849 td->td_retval[0] = fdp->fd_cmask;
3850 fdp->fd_cmask = uap->newmask & ALLPERMS;
3851 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
3852 return (0);
3853 }
3854
3855 /*
3856 * Void all references to file by ripping underlying filesystem
3857 * away from vnode.
3858 */
3859 #ifndef _SYS_SYSPROTO_H_
3860 struct revoke_args {
3861 char *path;
3862 };
3863 #endif
3864 int
3865 revoke(td, uap)
3866 struct thread *td;
3867 register struct revoke_args /* {
3868 char *path;
3869 } */ *uap;
3870 {
3871 struct vnode *vp;
3872 struct vattr vattr;
3873 int error;
3874 struct nameidata nd;
3875 int vfslocked;
3876
3877 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
3878 UIO_USERSPACE, uap->path, td);
3879 if ((error = namei(&nd)) != 0)
3880 return (error);
3881 vfslocked = NDHASGIANT(&nd);
3882 vp = nd.ni_vp;
3883 NDFREE(&nd, NDF_ONLY_PNBUF);
3884 if (vp->v_type != VCHR) {
3885 error = EINVAL;
3886 goto out;
3887 }
3888 #ifdef MAC
3889 error = mac_check_vnode_revoke(td->td_ucred, vp);
3890 if (error)
3891 goto out;
3892 #endif
3893 error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
3894 if (error)
3895 goto out;
3896 if (td->td_ucred->cr_uid != vattr.va_uid) {
3897 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
3898 if (error)
3899 goto out;
3900 }
3901 if (vcount(vp) > 1)
3902 VOP_REVOKE(vp, REVOKEALL);
3903 out:
3904 vput(vp);
3905 VFS_UNLOCK_GIANT(vfslocked);
3906 return (error);
3907 }
3908
3909 /*
3910 * Convert a user file descriptor to a kernel file entry.
3911 * A reference on the file entry is held upon returning.
3912 */
3913 int
3914 getvnode(fdp, fd, fpp)
3915 struct filedesc *fdp;
3916 int fd;
3917 struct file **fpp;
3918 {
3919 int error;
3920 struct file *fp;
3921
3922 fp = NULL;
3923 if (fdp == NULL)
3924 error = EBADF;
3925 else {
3926 FILEDESC_LOCK(fdp);
3927 if ((u_int)fd >= fdp->fd_nfiles ||
3928 (fp = fdp->fd_ofiles[fd]) == NULL)
3929 error = EBADF;
3930 else if (fp->f_vnode == NULL) {
3931 fp = NULL;
3932 error = EINVAL;
3933 } else {
3934 fhold(fp);
3935 error = 0;
3936 }
3937 FILEDESC_UNLOCK(fdp);
3938 }
3939 *fpp = fp;
3940 return (error);
3941 }
3942
3943 /*
3944 * Get (NFS) file handle
3945 */
3946 #ifndef _SYS_SYSPROTO_H_
3947 struct lgetfh_args {
3948 char *fname;
3949 fhandle_t *fhp;
3950 };
3951 #endif
3952 int
3953 lgetfh(td, uap)
3954 struct thread *td;
3955 register struct lgetfh_args *uap;
3956 {
3957 struct nameidata nd;
3958 fhandle_t fh;
3959 register struct vnode *vp;
3960 int vfslocked;
3961 int error;
3962
3963 error = suser(td);
3964 if (error)
3965 return (error);
3966 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
3967 UIO_USERSPACE, uap->fname, td);
3968 error = namei(&nd);
3969 if (error)
3970 return (error);
3971 vfslocked = NDHASGIANT(&nd);
3972 NDFREE(&nd, NDF_ONLY_PNBUF);
3973 vp = nd.ni_vp;
3974 bzero(&fh, sizeof(fh));
3975 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3976 error = VFS_VPTOFH(vp, &fh.fh_fid);
3977 vput(vp);
3978 VFS_UNLOCK_GIANT(vfslocked);
3979 if (error)
3980 return (error);
3981 error = copyout(&fh, uap->fhp, sizeof (fh));
3982 return (error);
3983 }
3984
3985 #ifndef _SYS_SYSPROTO_H_
3986 struct getfh_args {
3987 char *fname;
3988 fhandle_t *fhp;
3989 };
3990 #endif
3991 int
3992 getfh(td, uap)
3993 struct thread *td;
3994 register struct getfh_args *uap;
3995 {
3996 struct nameidata nd;
3997 fhandle_t fh;
3998 register struct vnode *vp;
3999 int vfslocked;
4000 int error;
4001
4002 error = suser(td);
4003 if (error)
4004 return (error);
4005 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
4006 UIO_USERSPACE, uap->fname, td);
4007 error = namei(&nd);
4008 if (error)
4009 return (error);
4010 vfslocked = NDHASGIANT(&nd);
4011 NDFREE(&nd, NDF_ONLY_PNBUF);
4012 vp = nd.ni_vp;
4013 bzero(&fh, sizeof(fh));
4014 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
4015 error = VFS_VPTOFH(vp, &fh.fh_fid);
4016 vput(vp);
4017 VFS_UNLOCK_GIANT(vfslocked);
4018 if (error)
4019 return (error);
4020 error = copyout(&fh, uap->fhp, sizeof (fh));
4021 return (error);
4022 }
4023
4024 /*
4025 * syscall for the rpc.lockd to use to translate a NFS file handle into
4026 * an open descriptor.
4027 *
4028 * warning: do not remove the suser() call or this becomes one giant
4029 * security hole.
4030 *
4031 * MP SAFE
4032 */
4033 #ifndef _SYS_SYSPROTO_H_
4034 struct fhopen_args {
4035 const struct fhandle *u_fhp;
4036 int flags;
4037 };
4038 #endif
4039 int
4040 fhopen(td, uap)
4041 struct thread *td;
4042 struct fhopen_args /* {
4043 const struct fhandle *u_fhp;
4044 int flags;
4045 } */ *uap;
4046 {
4047 struct proc *p = td->td_proc;
4048 struct mount *mp;
4049 struct vnode *vp;
4050 struct fhandle fhp;
4051 struct vattr vat;
4052 struct vattr *vap = &vat;
4053 struct flock lf;
4054 struct file *fp;
4055 register struct filedesc *fdp = p->p_fd;
4056 int fmode, mode, error, type;
4057 struct file *nfp;
4058 int indx;
4059
4060 error = suser(td);
4061 if (error)
4062 return (error);
4063 fmode = FFLAGS(uap->flags);
4064 /* why not allow a non-read/write open for our lockd? */
4065 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
4066 return (EINVAL);
4067 error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
4068 if (error)
4069 return(error);
4070 /* find the mount point */
4071 mtx_lock(&Giant);
4072 mp = vfs_getvfs(&fhp.fh_fsid);
4073 if (mp == NULL) {
4074 error = ESTALE;
4075 goto out_nomp;
4076 }
4077 /* now give me my vnode, it gets returned to me locked */
4078 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
4079 if (error)
4080 goto out;
4081 /*
4082 * from now on we have to make sure not
4083 * to forget about the vnode
4084 * any error that causes an abort must vput(vp)
4085 * just set error = err and 'goto bad;'.
4086 */
4087
4088 /*
4089 * from vn_open
4090 */
4091 if (vp->v_type == VLNK) {
4092 error = EMLINK;
4093 goto bad;
4094 }
4095 if (vp->v_type == VSOCK) {
4096 error = EOPNOTSUPP;
4097 goto bad;
4098 }
4099 mode = 0;
4100 if (fmode & (FWRITE | O_TRUNC)) {
4101 if (vp->v_type == VDIR) {
4102 error = EISDIR;
4103 goto bad;
4104 }
4105 error = vn_writechk(vp);
4106 if (error)
4107 goto bad;
4108 mode |= VWRITE;
4109 }
4110 if (fmode & FREAD)
4111 mode |= VREAD;
4112 if (fmode & O_APPEND)
4113 mode |= VAPPEND;
4114 #ifdef MAC
4115 error = mac_check_vnode_open(td->td_ucred, vp, mode);
4116 if (error)
4117 goto bad;
4118 #endif
4119 if (mode) {
4120 error = VOP_ACCESS(vp, mode, td->td_ucred, td);
4121 if (error)
4122 goto bad;
4123 }
4124 if (fmode & O_TRUNC) {
4125 VOP_UNLOCK(vp, 0, td); /* XXX */
4126 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
4127 vrele(vp);
4128 goto out;
4129 }
4130 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4131 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */
4132 #ifdef MAC
4133 /*
4134 * We don't yet have fp->f_cred, so use td->td_ucred, which
4135 * should be right.
4136 */
4137 error = mac_check_vnode_write(td->td_ucred, td->td_ucred, vp);
4138 if (error == 0) {
4139 #endif
4140 VATTR_NULL(vap);
4141 vap->va_size = 0;
4142 error = VOP_SETATTR(vp, vap, td->td_ucred, td);
4143 #ifdef MAC
4144 }
4145 #endif
4146 vn_finished_write(mp);
4147 if (error)
4148 goto bad;
4149 }
4150 error = VOP_OPEN(vp, fmode, td->td_ucred, td, -1);
4151 if (error)
4152 goto bad;
4153
4154 if (fmode & FWRITE)
4155 vp->v_writecount++;
4156
4157 /*
4158 * end of vn_open code
4159 */
4160
4161 if ((error = falloc(td, &nfp, &indx)) != 0) {
4162 if (fmode & FWRITE)
4163 vp->v_writecount--;
4164 goto bad;
4165 }
4166 /* An extra reference on `nfp' has been held for us by falloc(). */
4167 fp = nfp;
4168
4169 nfp->f_vnode = vp;
4170 nfp->f_data = vp;
4171 nfp->f_flag = fmode & FMASK;
4172 nfp->f_ops = &vnops;
4173 nfp->f_type = DTYPE_VNODE;
4174 if (fmode & (O_EXLOCK | O_SHLOCK)) {
4175 lf.l_whence = SEEK_SET;
4176 lf.l_start = 0;
4177 lf.l_len = 0;
4178 if (fmode & O_EXLOCK)
4179 lf.l_type = F_WRLCK;
4180 else
4181 lf.l_type = F_RDLCK;
4182 type = F_FLOCK;
4183 if ((fmode & FNONBLOCK) == 0)
4184 type |= F_WAIT;
4185 VOP_UNLOCK(vp, 0, td);
4186 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
4187 type)) != 0) {
4188 /*
4189 * The lock request failed. Normally close the
4190 * descriptor but handle the case where someone might
4191 * have dup()d or close()d it when we weren't looking.
4192 */
4193 fdclose(fdp, fp, indx, td);
4194
4195 /*
4196 * release our private reference
4197 */
4198 fdrop(fp, td);
4199 goto out;
4200 }
4201 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4202 fp->f_flag |= FHASLOCK;
4203 }
4204
4205 VOP_UNLOCK(vp, 0, td);
4206 fdrop(fp, td);
4207 vfs_rel(mp);
4208 mtx_unlock(&Giant);
4209 td->td_retval[0] = indx;
4210 return (0);
4211
4212 bad:
4213 vput(vp);
4214 out:
4215 vfs_rel(mp);
4216 out_nomp:
4217 mtx_unlock(&Giant);
4218 return (error);
4219 }
4220
4221 /*
4222 * Stat an (NFS) file handle.
4223 *
4224 * MP SAFE
4225 */
4226 #ifndef _SYS_SYSPROTO_H_
4227 struct fhstat_args {
4228 struct fhandle *u_fhp;
4229 struct stat *sb;
4230 };
4231 #endif
4232 int
4233 fhstat(td, uap)
4234 struct thread *td;
4235 register struct fhstat_args /* {
4236 struct fhandle *u_fhp;
4237 struct stat *sb;
4238 } */ *uap;
4239 {
4240 struct stat sb;
4241 fhandle_t fh;
4242 struct mount *mp;
4243 struct vnode *vp;
4244 int error;
4245
4246 error = suser(td);
4247 if (error)
4248 return (error);
4249 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4250 if (error)
4251 return (error);
4252 mtx_lock(&Giant);
4253 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
4254 mtx_unlock(&Giant);
4255 return (ESTALE);
4256 }
4257 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) {
4258 vfs_rel(mp);
4259 mtx_unlock(&Giant);
4260 return (error);
4261 }
4262 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
4263 vput(vp);
4264 vfs_rel(mp);
4265 mtx_unlock(&Giant);
4266 if (error)
4267 return (error);
4268 error = copyout(&sb, uap->sb, sizeof(sb));
4269 return (error);
4270 }
4271
4272 /*
4273 * Implement fstatfs() for (NFS) file handles.
4274 *
4275 * MP SAFE
4276 */
4277 #ifndef _SYS_SYSPROTO_H_
4278 struct fhstatfs_args {
4279 struct fhandle *u_fhp;
4280 struct statfs *buf;
4281 };
4282 #endif
4283 int
4284 fhstatfs(td, uap)
4285 struct thread *td;
4286 struct fhstatfs_args /* {
4287 struct fhandle *u_fhp;
4288 struct statfs *buf;
4289 } */ *uap;
4290 {
4291 struct statfs sf;
4292 fhandle_t fh;
4293 int error;
4294
4295 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4296 if (error)
4297 return (error);
4298 error = kern_fhstatfs(td, fh, &sf);
4299 if (error)
4300 return (error);
4301 return (copyout(&sf, uap->buf, sizeof(sf)));
4302 }
4303
4304 int
4305 kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
4306 {
4307 struct statfs *sp;
4308 struct mount *mp;
4309 struct vnode *vp;
4310 int error;
4311
4312 error = suser(td);
4313 if (error)
4314 return (error);
4315 mtx_lock(&Giant);
4316 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
4317 mtx_unlock(&Giant);
4318 return (ESTALE);
4319 }
4320 error = VFS_FHTOVP(mp, &fh.fh_fid, &vp);
4321 if (error) {
4322 mtx_unlock(&Giant);
4323 vfs_rel(mp);
4324 return (error);
4325 }
4326 vput(vp);
4327 error = prison_canseemount(td->td_ucred, mp);
4328 if (error) {
4329 vfs_rel(mp);
4330 mtx_unlock(&Giant);
4331 return (error);
4332 }
4333 #ifdef MAC
4334 error = mac_check_mount_stat(td->td_ucred, mp);
4335 if (error) {
4336 vfs_rel(mp);
4337 mtx_unlock(&Giant);
4338 return (error);
4339 }
4340 #endif
4341 /*
4342 * Set these in case the underlying filesystem fails to do so.
4343 */
4344 sp = &mp->mnt_stat;
4345 sp->f_version = STATFS_VERSION;
4346 sp->f_namemax = NAME_MAX;
4347 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
4348 error = VFS_STATFS(mp, sp, td);
4349 if (error == 0)
4350 *buf = *sp;
4351 vfs_rel(mp);
4352 mtx_unlock(&Giant);
4353 return (error);
4354 }
4355
4356 /*
4357 * Syscall to push extended attribute configuration information into the
4358 * VFS. Accepts a path, which it converts to a mountpoint, as well as
4359 * a command (int cmd), and attribute name and misc data. For now, the
4360 * attribute name is left in userspace for consumption by the VFS_op.
4361 * It will probably be changed to be copied into sysspace by the
4362 * syscall in the future, once issues with various consumers of the
4363 * attribute code have raised their hands.
4364 *
4365 * Currently this is used only by UFS Extended Attributes.
4366 */
4367 int
4368 extattrctl(td, uap)
4369 struct thread *td;
4370 struct extattrctl_args /* {
4371 const char *path;
4372 int cmd;
4373 const char *filename;
4374 int attrnamespace;
4375 const char *attrname;
4376 } */ *uap;
4377 {
4378 struct vnode *filename_vp;
4379 struct nameidata nd;
4380 struct mount *mp, *mp_writable;
4381 char attrname[EXTATTR_MAXNAMELEN];
4382 int vfslocked, fnvfslocked, error;
4383
4384 AUDIT_ARG(cmd, uap->cmd);
4385 AUDIT_ARG(value, uap->attrnamespace);
4386 /*
4387 * uap->attrname is not always defined. We check again later when we
4388 * invoke the VFS call so as to pass in NULL there if needed.
4389 */
4390 if (uap->attrname != NULL) {
4391 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
4392 NULL);
4393 if (error)
4394 return (error);
4395 }
4396 AUDIT_ARG(text, attrname);
4397
4398 vfslocked = fnvfslocked = 0;
4399 /*
4400 * uap->filename is not always defined. If it is, grab a vnode lock,
4401 * which VFS_EXTATTRCTL() will later release.
4402 */
4403 filename_vp = NULL;
4404 if (uap->filename != NULL) {
4405 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF |
4406 AUDITVNODE2, UIO_USERSPACE, uap->filename, td);
4407 error = namei(&nd);
4408 if (error)
4409 return (error);
4410 fnvfslocked = NDHASGIANT(&nd);
4411 filename_vp = nd.ni_vp;
4412 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
4413 }
4414
4415 /* uap->path is always defined. */
4416 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4417 uap->path, td);
4418 error = namei(&nd);
4419 if (error) {
4420 if (filename_vp != NULL)
4421 vput(filename_vp);
4422 goto out;
4423 }
4424 vfslocked = NDHASGIANT(&nd);
4425 mp = nd.ni_vp->v_mount;
4426 error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
4427 NDFREE(&nd, 0);
4428 if (error) {
4429 if (filename_vp != NULL)
4430 vput(filename_vp);
4431 goto out;
4432 }
4433
4434 error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
4435 uap->attrname != NULL ? attrname : NULL, td);
4436
4437 vn_finished_write(mp_writable);
4438 /*
4439 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
4440 * filename_vp, so vrele it if it is defined.
4441 */
4442 if (filename_vp != NULL)
4443 vrele(filename_vp);
4444 out:
4445 VFS_UNLOCK_GIANT(fnvfslocked);
4446 VFS_UNLOCK_GIANT(vfslocked);
4447 return (error);
4448 }
4449
4450 /*-
4451 * Set a named extended attribute on a file or directory
4452 *
4453 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4454 * kernelspace string pointer "attrname", userspace buffer
4455 * pointer "data", buffer length "nbytes", thread "td".
4456 * Returns: 0 on success, an error number otherwise
4457 * Locks: none
4458 * References: vp must be a valid reference for the duration of the call
4459 */
4460 static int
4461 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4462 void *data, size_t nbytes, struct thread *td)
4463 {
4464 struct mount *mp;
4465 struct uio auio;
4466 struct iovec aiov;
4467 ssize_t cnt;
4468 int error;
4469
4470 VFS_ASSERT_GIANT(vp->v_mount);
4471 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4472 if (error)
4473 return (error);
4474 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4475 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4476
4477 aiov.iov_base = data;
4478 aiov.iov_len = nbytes;
4479 auio.uio_iov = &aiov;
4480 auio.uio_iovcnt = 1;
4481 auio.uio_offset = 0;
4482 if (nbytes > INT_MAX) {
4483 error = EINVAL;
4484 goto done;
4485 }
4486 auio.uio_resid = nbytes;
4487 auio.uio_rw = UIO_WRITE;
4488 auio.uio_segflg = UIO_USERSPACE;
4489 auio.uio_td = td;
4490 cnt = nbytes;
4491
4492 #ifdef MAC
4493 error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
4494 attrname, &auio);
4495 if (error)
4496 goto done;
4497 #endif
4498
4499 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
4500 td->td_ucred, td);
4501 cnt -= auio.uio_resid;
4502 td->td_retval[0] = cnt;
4503
4504 done:
4505 VOP_UNLOCK(vp, 0, td);
4506 vn_finished_write(mp);
4507 return (error);
4508 }
4509
4510 int
4511 extattr_set_fd(td, uap)
4512 struct thread *td;
4513 struct extattr_set_fd_args /* {
4514 int fd;
4515 int attrnamespace;
4516 const char *attrname;
4517 void *data;
4518 size_t nbytes;
4519 } */ *uap;
4520 {
4521 struct file *fp;
4522 char attrname[EXTATTR_MAXNAMELEN];
4523 int vfslocked, error;
4524
4525 AUDIT_ARG(fd, uap->fd);
4526 AUDIT_ARG(value, uap->attrnamespace);
4527 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4528 if (error)
4529 return (error);
4530 AUDIT_ARG(text, attrname);
4531
4532 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4533 if (error)
4534 return (error);
4535
4536 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
4537 error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
4538 attrname, uap->data, uap->nbytes, td);
4539 fdrop(fp, td);
4540 VFS_UNLOCK_GIANT(vfslocked);
4541
4542 return (error);
4543 }
4544
4545 int
4546 extattr_set_file(td, uap)
4547 struct thread *td;
4548 struct extattr_set_file_args /* {
4549 const char *path;
4550 int attrnamespace;
4551 const char *attrname;
4552 void *data;
4553 size_t nbytes;
4554 } */ *uap;
4555 {
4556 struct nameidata nd;
4557 char attrname[EXTATTR_MAXNAMELEN];
4558 int vfslocked, error;
4559
4560 AUDIT_ARG(value, uap->attrnamespace);
4561 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4562 if (error)
4563 return (error);
4564 AUDIT_ARG(text, attrname);
4565
4566 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4567 uap->path, td);
4568 error = namei(&nd);
4569 if (error)
4570 return (error);
4571 NDFREE(&nd, NDF_ONLY_PNBUF);
4572
4573 vfslocked = NDHASGIANT(&nd);
4574 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4575 uap->data, uap->nbytes, td);
4576
4577 vrele(nd.ni_vp);
4578 VFS_UNLOCK_GIANT(vfslocked);
4579 return (error);
4580 }
4581
4582 int
4583 extattr_set_link(td, uap)
4584 struct thread *td;
4585 struct extattr_set_link_args /* {
4586 const char *path;
4587 int attrnamespace;
4588 const char *attrname;
4589 void *data;
4590 size_t nbytes;
4591 } */ *uap;
4592 {
4593 struct nameidata nd;
4594 char attrname[EXTATTR_MAXNAMELEN];
4595 int vfslocked, error;
4596
4597 AUDIT_ARG(value, uap->attrnamespace);
4598 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4599 if (error)
4600 return (error);
4601 AUDIT_ARG(text, attrname);
4602
4603 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
4604 uap->path, td);
4605 error = namei(&nd);
4606 if (error)
4607 return (error);
4608 NDFREE(&nd, NDF_ONLY_PNBUF);
4609
4610 vfslocked = NDHASGIANT(&nd);
4611 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4612 uap->data, uap->nbytes, td);
4613
4614 vrele(nd.ni_vp);
4615 VFS_UNLOCK_GIANT(vfslocked);
4616 return (error);
4617 }
4618
4619 /*-
4620 * Get a named extended attribute on a file or directory
4621 *
4622 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4623 * kernelspace string pointer "attrname", userspace buffer
4624 * pointer "data", buffer length "nbytes", thread "td".
4625 * Returns: 0 on success, an error number otherwise
4626 * Locks: none
4627 * References: vp must be a valid reference for the duration of the call
4628 */
4629 static int
4630 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4631 void *data, size_t nbytes, struct thread *td)
4632 {
4633 struct uio auio, *auiop;
4634 struct iovec aiov;
4635 ssize_t cnt;
4636 size_t size, *sizep;
4637 int error;
4638
4639 VFS_ASSERT_GIANT(vp->v_mount);
4640 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4641 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4642
4643 /*
4644 * Slightly unusual semantics: if the user provides a NULL data
4645 * pointer, they don't want to receive the data, just the
4646 * maximum read length.
4647 */
4648 auiop = NULL;
4649 sizep = NULL;
4650 cnt = 0;
4651 if (data != NULL) {
4652 aiov.iov_base = data;
4653 aiov.iov_len = nbytes;
4654 auio.uio_iov = &aiov;
4655 auio.uio_iovcnt = 1;
4656 auio.uio_offset = 0;
4657 if (nbytes > INT_MAX) {
4658 error = EINVAL;
4659 goto done;
4660 }
4661 auio.uio_resid = nbytes;
4662 auio.uio_rw = UIO_READ;
4663 auio.uio_segflg = UIO_USERSPACE;
4664 auio.uio_td = td;
4665 auiop = &auio;
4666 cnt = nbytes;
4667 } else
4668 sizep = &size;
4669
4670 #ifdef MAC
4671 error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace,
4672 attrname, &auio);
4673 if (error)
4674 goto done;
4675 #endif
4676
4677 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
4678 td->td_ucred, td);
4679
4680 if (auiop != NULL) {
4681 cnt -= auio.uio_resid;
4682 td->td_retval[0] = cnt;
4683 } else
4684 td->td_retval[0] = size;
4685
4686 done:
4687 VOP_UNLOCK(vp, 0, td);
4688 return (error);
4689 }
4690
4691 int
4692 extattr_get_fd(td, uap)
4693 struct thread *td;
4694 struct extattr_get_fd_args /* {
4695 int fd;
4696 int attrnamespace;
4697 const char *attrname;
4698 void *data;
4699 size_t nbytes;
4700 } */ *uap;
4701 {
4702 struct file *fp;
4703 char attrname[EXTATTR_MAXNAMELEN];
4704 int vfslocked, error;
4705
4706 AUDIT_ARG(fd, uap->fd);
4707 AUDIT_ARG(value, uap->attrnamespace);
4708 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4709 if (error)
4710 return (error);
4711 AUDIT_ARG(text, attrname);
4712
4713 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4714 if (error)
4715 return (error);
4716
4717 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
4718 error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
4719 attrname, uap->data, uap->nbytes, td);
4720
4721 fdrop(fp, td);
4722 VFS_UNLOCK_GIANT(vfslocked);
4723 return (error);
4724 }
4725
4726 int
4727 extattr_get_file(td, uap)
4728 struct thread *td;
4729 struct extattr_get_file_args /* {
4730 const char *path;
4731 int attrnamespace;
4732 const char *attrname;
4733 void *data;
4734 size_t nbytes;
4735 } */ *uap;
4736 {
4737 struct nameidata nd;
4738 char attrname[EXTATTR_MAXNAMELEN];
4739 int vfslocked, error;
4740
4741 AUDIT_ARG(value, uap->attrnamespace);
4742 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4743 if (error)
4744 return (error);
4745 AUDIT_ARG(text, attrname);
4746
4747 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4748 uap->path, td);
4749 error = namei(&nd);
4750 if (error)
4751 return (error);
4752 NDFREE(&nd, NDF_ONLY_PNBUF);
4753
4754 vfslocked = NDHASGIANT(&nd);
4755 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4756 uap->data, uap->nbytes, td);
4757
4758 vrele(nd.ni_vp);
4759 VFS_UNLOCK_GIANT(vfslocked);
4760 return (error);
4761 }
4762
4763 int
4764 extattr_get_link(td, uap)
4765 struct thread *td;
4766 struct extattr_get_link_args /* {
4767 const char *path;
4768 int attrnamespace;
4769 const char *attrname;
4770 void *data;
4771 size_t nbytes;
4772 } */ *uap;
4773 {
4774 struct nameidata nd;
4775 char attrname[EXTATTR_MAXNAMELEN];
4776 int vfslocked, error;
4777
4778 AUDIT_ARG(value, uap->attrnamespace);
4779 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4780 if (error)
4781 return (error);
4782 AUDIT_ARG(text, attrname);
4783
4784 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
4785 uap->path, td);
4786 error = namei(&nd);
4787 if (error)
4788 return (error);
4789 NDFREE(&nd, NDF_ONLY_PNBUF);
4790
4791 vfslocked = NDHASGIANT(&nd);
4792 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4793 uap->data, uap->nbytes, td);
4794
4795 vrele(nd.ni_vp);
4796 VFS_UNLOCK_GIANT(vfslocked);
4797 return (error);
4798 }
4799
4800 /*
4801 * extattr_delete_vp(): Delete a named extended attribute on a file or
4802 * directory
4803 *
4804 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4805 * kernelspace string pointer "attrname", proc "p"
4806 * Returns: 0 on success, an error number otherwise
4807 * Locks: none
4808 * References: vp must be a valid reference for the duration of the call
4809 */
4810 static int
4811 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4812 struct thread *td)
4813 {
4814 struct mount *mp;
4815 int error;
4816
4817 VFS_ASSERT_GIANT(vp->v_mount);
4818 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4819 if (error)
4820 return (error);
4821 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4822 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4823
4824 #ifdef MAC
4825 error = mac_check_vnode_deleteextattr(td->td_ucred, vp, attrnamespace,
4826 attrname);
4827 if (error)
4828 goto done;
4829 #endif
4830
4831 error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, td->td_ucred,
4832 td);
4833 if (error == EOPNOTSUPP)
4834 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
4835 td->td_ucred, td);
4836 #ifdef MAC
4837 done:
4838 #endif
4839 VOP_UNLOCK(vp, 0, td);
4840 vn_finished_write(mp);
4841 return (error);
4842 }
4843
4844 int
4845 extattr_delete_fd(td, uap)
4846 struct thread *td;
4847 struct extattr_delete_fd_args /* {
4848 int fd;
4849 int attrnamespace;
4850 const char *attrname;
4851 } */ *uap;
4852 {
4853 struct file *fp;
4854 char attrname[EXTATTR_MAXNAMELEN];
4855 int vfslocked, error;
4856
4857 AUDIT_ARG(fd, uap->fd);
4858 AUDIT_ARG(value, uap->attrnamespace);
4859 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4860 if (error)
4861 return (error);
4862 AUDIT_ARG(text, attrname);
4863
4864 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4865 if (error)
4866 return (error);
4867
4868 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
4869 error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
4870 attrname, td);
4871 fdrop(fp, td);
4872 VFS_UNLOCK_GIANT(vfslocked);
4873 return (error);
4874 }
4875
4876 int
4877 extattr_delete_file(td, uap)
4878 struct thread *td;
4879 struct extattr_delete_file_args /* {
4880 const char *path;
4881 int attrnamespace;
4882 const char *attrname;
4883 } */ *uap;
4884 {
4885 struct nameidata nd;
4886 char attrname[EXTATTR_MAXNAMELEN];
4887 int vfslocked, error;
4888
4889 AUDIT_ARG(value, uap->attrnamespace);
4890 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4891 if (error)
4892 return(error);
4893 AUDIT_ARG(text, attrname);
4894
4895 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4896 uap->path, td);
4897 error = namei(&nd);
4898 if (error)
4899 return(error);
4900 NDFREE(&nd, NDF_ONLY_PNBUF);
4901
4902 vfslocked = NDHASGIANT(&nd);
4903 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4904 vrele(nd.ni_vp);
4905 VFS_UNLOCK_GIANT(vfslocked);
4906 return(error);
4907 }
4908
4909 int
4910 extattr_delete_link(td, uap)
4911 struct thread *td;
4912 struct extattr_delete_link_args /* {
4913 const char *path;
4914 int attrnamespace;
4915 const char *attrname;
4916 } */ *uap;
4917 {
4918 struct nameidata nd;
4919 char attrname[EXTATTR_MAXNAMELEN];
4920 int vfslocked, error;
4921
4922 AUDIT_ARG(value, uap->attrnamespace);
4923 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4924 if (error)
4925 return(error);
4926 AUDIT_ARG(text, attrname);
4927
4928 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
4929 uap->path, td);
4930 error = namei(&nd);
4931 if (error)
4932 return(error);
4933 NDFREE(&nd, NDF_ONLY_PNBUF);
4934
4935 vfslocked = NDHASGIANT(&nd);
4936 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4937 vrele(nd.ni_vp);
4938 VFS_UNLOCK_GIANT(vfslocked);
4939 return(error);
4940 }
4941
4942 /*-
4943 * Retrieve a list of extended attributes on a file or directory.
4944 *
4945 * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
4946 * userspace buffer pointer "data", buffer length "nbytes",
4947 * thread "td".
4948 * Returns: 0 on success, an error number otherwise
4949 * Locks: none
4950 * References: vp must be a valid reference for the duration of the call
4951 */
4952 static int
4953 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
4954 size_t nbytes, struct thread *td)
4955 {
4956 struct uio auio, *auiop;
4957 size_t size, *sizep;
4958 struct iovec aiov;
4959 ssize_t cnt;
4960 int error;
4961
4962 VFS_ASSERT_GIANT(vp->v_mount);
4963 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4964 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4965
4966 auiop = NULL;
4967 sizep = NULL;
4968 cnt = 0;
4969 if (data != NULL) {
4970 aiov.iov_base = data;
4971 aiov.iov_len = nbytes;
4972 auio.uio_iov = &aiov;
4973 auio.uio_iovcnt = 1;
4974 auio.uio_offset = 0;
4975 if (nbytes > INT_MAX) {
4976 error = EINVAL;
4977 goto done;
4978 }
4979 auio.uio_resid = nbytes;
4980 auio.uio_rw = UIO_READ;
4981 auio.uio_segflg = UIO_USERSPACE;
4982 auio.uio_td = td;
4983 auiop = &auio;
4984 cnt = nbytes;
4985 } else
4986 sizep = &size;
4987
4988 #ifdef MAC
4989 error = mac_check_vnode_listextattr(td->td_ucred, vp, attrnamespace);
4990 if (error)
4991 goto done;
4992 #endif
4993
4994 error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
4995 td->td_ucred, td);
4996
4997 if (auiop != NULL) {
4998 cnt -= auio.uio_resid;
4999 td->td_retval[0] = cnt;
5000 } else
5001 td->td_retval[0] = size;
5002
5003 done:
5004 VOP_UNLOCK(vp, 0, td);
5005 return (error);
5006 }
5007
5008
5009 int
5010 extattr_list_fd(td, uap)
5011 struct thread *td;
5012 struct extattr_list_fd_args /* {
5013 int fd;
5014 int attrnamespace;
5015 void *data;
5016 size_t nbytes;
5017 } */ *uap;
5018 {
5019 struct file *fp;
5020 int vfslocked, error;
5021
5022 AUDIT_ARG(fd, uap->fd);
5023 AUDIT_ARG(value, uap->attrnamespace);
5024 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
5025 if (error)
5026 return (error);
5027
5028 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
5029 error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
5030 uap->nbytes, td);
5031
5032 fdrop(fp, td);
5033 VFS_UNLOCK_GIANT(vfslocked);
5034 return (error);
5035 }
5036
5037 int
5038 extattr_list_file(td, uap)
5039 struct thread*td;
5040 struct extattr_list_file_args /* {
5041 const char *path;
5042 int attrnamespace;
5043 void *data;
5044 size_t nbytes;
5045 } */ *uap;
5046 {
5047 struct nameidata nd;
5048 int vfslocked, error;
5049
5050 AUDIT_ARG(value, uap->attrnamespace);
5051 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
5052 uap->path, td);
5053 error = namei(&nd);
5054 if (error)
5055 return (error);
5056 NDFREE(&nd, NDF_ONLY_PNBUF);
5057
5058 vfslocked = NDHASGIANT(&nd);
5059 error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
5060 uap->nbytes, td);
5061
5062 vrele(nd.ni_vp);
5063 VFS_UNLOCK_GIANT(vfslocked);
5064 return (error);
5065 }
5066
5067 int
5068 extattr_list_link(td, uap)
5069 struct thread*td;
5070 struct extattr_list_link_args /* {
5071 const char *path;
5072 int attrnamespace;
5073 void *data;
5074 size_t nbytes;
5075 } */ *uap;
5076 {
5077 struct nameidata nd;
5078 int vfslocked, error;
5079
5080 AUDIT_ARG(value, uap->attrnamespace);
5081 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
5082 uap->path, td);
5083 error = namei(&nd);
5084 if (error)
5085 return (error);
5086 NDFREE(&nd, NDF_ONLY_PNBUF);
5087
5088 vfslocked = NDHASGIANT(&nd);
5089 error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
5090 uap->nbytes, td);
5091
5092 vrele(nd.ni_vp);
5093 VFS_UNLOCK_GIANT(vfslocked);
5094 return (error);
5095 }
Cache object: 9901ccde3d5dfa0f8aca54902a65b7a4
|