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