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