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