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