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