2005-01-06 23:35:40 +00:00
|
|
|
/*-
|
2017-11-20 19:43:44 +00:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*
|
1994-05-24 10:09:53 +00:00
|
|
|
* Copyright (c) 1989, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
* (c) UNIX System Laboratories, Inc.
|
|
|
|
* All or some portions of this file are derived from material licensed
|
|
|
|
* to the University of California by American Telephone and Telegraph
|
|
|
|
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
|
|
|
* the permission of UNIX System Laboratories, Inc.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2016-09-15 13:16:20 +00:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1994-05-24 10:09:53 +00:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
|
|
|
|
*/
|
|
|
|
|
2003-06-11 00:56:59 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2011-08-11 12:30:23 +00:00
|
|
|
#include "opt_capsicum.h"
|
2008-02-23 01:01:49 +00:00
|
|
|
#include "opt_ktrace.h"
|
1997-12-16 17:40:42 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
2000-05-05 09:59:14 +00:00
|
|
|
#include <sys/bio.h>
|
1999-02-25 15:54:06 +00:00
|
|
|
#include <sys/buf.h>
|
2014-03-16 10:55:57 +00:00
|
|
|
#include <sys/capsicum.h>
|
2010-03-03 16:18:04 +00:00
|
|
|
#include <sys/disk.h>
|
1997-02-10 02:22:35 +00:00
|
|
|
#include <sys/sysent.h>
|
2002-08-01 17:47:56 +00:00
|
|
|
#include <sys/malloc.h>
|
1999-09-11 00:46:08 +00:00
|
|
|
#include <sys/mount.h>
|
2000-10-20 07:58:15 +00:00
|
|
|
#include <sys/mutex.h>
|
1995-11-12 06:43:28 +00:00
|
|
|
#include <sys/sysproto.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/namei.h>
|
|
|
|
#include <sys/filedesc.h>
|
|
|
|
#include <sys/kernel.h>
|
1997-03-23 03:37:54 +00:00
|
|
|
#include <sys/fcntl.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/file.h>
|
2007-04-05 21:10:53 +00:00
|
|
|
#include <sys/filio.h>
|
2003-04-29 13:36:06 +00:00
|
|
|
#include <sys/limits.h>
|
1998-11-03 14:29:09 +00:00
|
|
|
#include <sys/linker.h>
|
2013-03-09 02:32:23 +00:00
|
|
|
#include <sys/rwlock.h>
|
2008-11-05 19:40:36 +00:00
|
|
|
#include <sys/sdt.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/stat.h>
|
2001-03-28 11:52:56 +00:00
|
|
|
#include <sys/sx.h>
|
1996-09-03 14:25:27 +00:00
|
|
|
#include <sys/unistd.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/vnode.h>
|
2006-11-06 13:42:10 +00:00
|
|
|
#include <sys/priv.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/dirent.h>
|
2001-02-21 06:39:57 +00:00
|
|
|
#include <sys/jail.h>
|
2002-09-01 20:37:28 +00:00
|
|
|
#include <sys/syscallsubr.h>
|
2001-08-23 13:51:17 +00:00
|
|
|
#include <sys/sysctl.h>
|
2008-02-23 01:01:49 +00:00
|
|
|
#ifdef KTRACE
|
|
|
|
#include <sys/ktrace.h>
|
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2002-03-26 15:33:44 +00:00
|
|
|
#include <machine/stdarg.h>
|
2001-08-23 13:51:17 +00:00
|
|
|
|
Add pathname and/or vnode argument auditing for the following system calls:
quotactl, statfs, fstatfs, fchdir, chdir, chroot, open, mknod, mkfifo,
link, symlink, undelete, unlink, access, eaccess, stat, lstat, pathconf,
readlink, chflags, lchflags, fchflags, chmod, lchmod, fchmod, chown,
lchown, fchown, utimes, lutimes, futimes, truncate, ftruncate, fsync,
rename, mkdir, rmdir, getdirentries, revoke, lgetfh, getfh, extattrctl,
extattr_set_file, extattr_set_link, extattr_get_file, extattr_get_link,
extattr_delete_file, extattr_delete_link, extattr_list_file, extattr_list_link.
In many cases the pathname and vnode auditing is done within namei lookup
instead of directly in the system call.
Audit the remaining arguments to these system calls:
fstatfs, fchdir, open, mknod, chflags, lchflags, fchflags, chmod, lchmod,
fchmod, chown, lchown, fchown, futimes, ftruncate, fsync, mkdir,
getdirentries.
2006-02-22 16:04:20 +00:00
|
|
|
#include <security/audit/audit.h>
|
2006-10-22 11:52:19 +00:00
|
|
|
#include <security/mac/mac_framework.h>
|
Add pathname and/or vnode argument auditing for the following system calls:
quotactl, statfs, fstatfs, fchdir, chdir, chroot, open, mknod, mkfifo,
link, symlink, undelete, unlink, access, eaccess, stat, lstat, pathconf,
readlink, chflags, lchflags, fchflags, chmod, lchmod, fchmod, chown,
lchown, fchown, utimes, lutimes, futimes, truncate, ftruncate, fsync,
rename, mkdir, rmdir, getdirentries, revoke, lgetfh, getfh, extattrctl,
extattr_set_file, extattr_set_link, extattr_get_file, extattr_get_link,
extattr_delete_file, extattr_delete_link, extattr_list_file, extattr_list_link.
In many cases the pathname and vnode auditing is done within namei lookup
instead of directly in the system call.
Audit the remaining arguments to these system calls:
fstatfs, fchdir, open, mknod, chflags, lchflags, fchflags, chmod, lchmod,
fchmod, chown, lchown, fchown, futimes, ftruncate, fsync, mkdir,
getdirentries.
2006-02-22 16:04:20 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <vm/vm.h>
|
1995-12-07 12:48:31 +00:00
|
|
|
#include <vm/vm_object.h>
|
2000-11-18 21:01:04 +00:00
|
|
|
#include <vm/vm_page.h>
|
2002-03-20 04:09:59 +00:00
|
|
|
#include <vm/uma.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2012-01-08 23:06:53 +00:00
|
|
|
#include <ufs/ufs/quota.h>
|
|
|
|
|
2012-03-08 20:34:13 +00:00
|
|
|
MALLOC_DEFINE(M_FADVISE, "fadvise", "posix_fadvise(2) information");
|
2011-11-04 04:02:50 +00:00
|
|
|
|
2008-11-05 19:40:36 +00:00
|
|
|
SDT_PROVIDER_DEFINE(vfs);
|
2013-11-26 08:46:27 +00:00
|
|
|
SDT_PROBE_DEFINE2(vfs, , stat, mode, "char *", "int");
|
|
|
|
SDT_PROBE_DEFINE2(vfs, , stat, reg, "char *", "int");
|
2008-11-05 19:40:36 +00:00
|
|
|
|
2013-03-21 22:59:01 +00:00
|
|
|
static int kern_chflagsat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, u_long flags, int atflag);
|
2013-03-21 22:44:33 +00:00
|
|
|
static int setfflags(struct thread *td, struct vnode *, u_long);
|
2015-01-23 21:07:08 +00:00
|
|
|
static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
|
|
|
|
static int getutimens(const struct timespec *, enum uio_seg,
|
|
|
|
struct timespec *, int *);
|
2002-03-19 21:25:46 +00:00
|
|
|
static int setutimes(struct thread *td, struct vnode *,
|
2002-07-17 02:03:19 +00:00
|
|
|
const struct timespec *, int, int);
|
2002-03-19 21:25:46 +00:00
|
|
|
static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
|
|
|
|
struct thread *td);
|
2018-12-07 15:17:29 +00:00
|
|
|
static int kern_fhlinkat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, fhandle_t *fhp);
|
|
|
|
static int kern_getfhat(struct thread *td, int flags, int fd,
|
|
|
|
const char *path, enum uio_seg pathseg, fhandle_t *fhp);
|
|
|
|
static int kern_readlink_vp(struct vnode *vp, char *buf, enum uio_seg bufseg,
|
|
|
|
size_t count, struct thread *td);
|
|
|
|
static int kern_linkat_vp(struct thread *td, struct vnode *vp, int fd,
|
|
|
|
const char *path, enum uio_seg segflag);
|
1997-10-23 09:29:09 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Sync each mounted filesystem.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1995-10-08 00:06:22 +00:00
|
|
|
struct sync_args {
|
2004-01-11 19:52:10 +00:00
|
|
|
int dummy;
|
1995-10-08 00:06:22 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_sync(struct thread *td, struct sync_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp, *nmp;
|
2012-10-22 17:50:54 +00:00
|
|
|
int save;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
Change and clean the mutex lock interface.
mtx_enter(lock, type) becomes:
mtx_lock(lock) for sleep locks (MTX_DEF-initialized locks)
mtx_lock_spin(lock) for spin locks (MTX_SPIN-initialized)
similarily, for releasing a lock, we now have:
mtx_unlock(lock) for MTX_DEF and mtx_unlock_spin(lock) for MTX_SPIN.
We change the caller interface for the two different types of locks
because the semantics are entirely different for each case, and this
makes it explicitly clear and, at the same time, it rids us of the
extra `type' argument.
The enter->lock and exit->unlock change has been made with the idea
that we're "locking data" and not "entering locked code" in mind.
Further, remove all additional "flags" previously passed to the
lock acquire/release routines with the exception of two:
MTX_QUIET and MTX_NOSWITCH
The functionality of these flags is preserved and they can be passed
to the lock/unlock routines by calling the corresponding wrappers:
mtx_{lock, unlock}_flags(lock, flag(s)) and
mtx_{lock, unlock}_spin_flags(lock, flag(s)) for MTX_DEF and MTX_SPIN
locks, respectively.
Re-inline some lock acq/rel code; in the sleep lock case, we only
inline the _obtain_lock()s in order to ensure that the inlined code
fits into a cache line. In the spin lock case, we inline recursion and
actually only perform a function call if we need to spin. This change
has been made with the idea that we generally tend to avoid spin locks
and that also the spin locks that we do have and are heavily used
(i.e. sched_lock) do recurse, and therefore in an effort to reduce
function call overhead for some architectures (such as alpha), we
inline recursion for this case.
Create a new malloc type for the witness code and retire from using
the M_DEV type. The new type is called M_WITNESS and is only declared
if WITNESS is enabled.
Begin cleaning up some machdep/mutex.h code - specifically updated the
"optimized" inlined code in alpha/mutex.h and wrote MTX_LOCK_SPIN
and MTX_UNLOCK_SPIN asm macros for the i386/mutex.h as we presently
need those.
Finally, caught up to the interface changes in all sys code.
Contributors: jake, jhb, jasone (in no particular order)
2001-02-09 06:11:45 +00:00
|
|
|
mtx_lock(&mountlist_mtx);
|
1999-11-20 10:00:46 +00:00
|
|
|
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
|
2008-11-02 10:15:42 +00:00
|
|
|
if (vfs_busy(mp, MBF_NOWAIT | MBF_MNTLSTLOCK)) {
|
1999-11-20 10:00:46 +00:00
|
|
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
1997-02-10 02:22:35 +00:00
|
|
|
continue;
|
|
|
|
}
|
2000-07-11 22:07:57 +00:00
|
|
|
if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
|
|
|
|
vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
|
2012-02-06 11:04:36 +00:00
|
|
|
save = curthread_pflags_set(TDP_SYNCIO);
|
1995-05-21 21:39:31 +00:00
|
|
|
vfs_msync(mp, MNT_NOWAIT);
|
2009-05-11 15:33:26 +00:00
|
|
|
VFS_SYNC(mp, MNT_NOWAIT);
|
2012-02-06 11:04:36 +00:00
|
|
|
curthread_pflags_restore(save);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
Change and clean the mutex lock interface.
mtx_enter(lock, type) becomes:
mtx_lock(lock) for sleep locks (MTX_DEF-initialized locks)
mtx_lock_spin(lock) for spin locks (MTX_SPIN-initialized)
similarily, for releasing a lock, we now have:
mtx_unlock(lock) for MTX_DEF and mtx_unlock_spin(lock) for MTX_SPIN.
We change the caller interface for the two different types of locks
because the semantics are entirely different for each case, and this
makes it explicitly clear and, at the same time, it rids us of the
extra `type' argument.
The enter->lock and exit->unlock change has been made with the idea
that we're "locking data" and not "entering locked code" in mind.
Further, remove all additional "flags" previously passed to the
lock acquire/release routines with the exception of two:
MTX_QUIET and MTX_NOSWITCH
The functionality of these flags is preserved and they can be passed
to the lock/unlock routines by calling the corresponding wrappers:
mtx_{lock, unlock}_flags(lock, flag(s)) and
mtx_{lock, unlock}_spin_flags(lock, flag(s)) for MTX_DEF and MTX_SPIN
locks, respectively.
Re-inline some lock acq/rel code; in the sleep lock case, we only
inline the _obtain_lock()s in order to ensure that the inlined code
fits into a cache line. In the spin lock case, we inline recursion and
actually only perform a function call if we need to spin. This change
has been made with the idea that we generally tend to avoid spin locks
and that also the spin locks that we do have and are heavily used
(i.e. sched_lock) do recurse, and therefore in an effort to reduce
function call overhead for some architectures (such as alpha), we
inline recursion for this case.
Create a new malloc type for the witness code and retire from using
the M_DEV type. The new type is called M_WITNESS and is only declared
if WITNESS is enabled.
Begin cleaning up some machdep/mutex.h code - specifically updated the
"optimized" inlined code in alpha/mutex.h and wrote MTX_LOCK_SPIN
and MTX_UNLOCK_SPIN asm macros for the i386/mutex.h as we presently
need those.
Finally, caught up to the interface changes in all sys code.
Contributors: jake, jhb, jasone (in no particular order)
2001-02-09 06:11:45 +00:00
|
|
|
mtx_lock(&mountlist_mtx);
|
1999-11-20 10:00:46 +00:00
|
|
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
2008-08-31 14:26:08 +00:00
|
|
|
vfs_unbusy(mp);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
Change and clean the mutex lock interface.
mtx_enter(lock, type) becomes:
mtx_lock(lock) for sleep locks (MTX_DEF-initialized locks)
mtx_lock_spin(lock) for spin locks (MTX_SPIN-initialized)
similarily, for releasing a lock, we now have:
mtx_unlock(lock) for MTX_DEF and mtx_unlock_spin(lock) for MTX_SPIN.
We change the caller interface for the two different types of locks
because the semantics are entirely different for each case, and this
makes it explicitly clear and, at the same time, it rids us of the
extra `type' argument.
The enter->lock and exit->unlock change has been made with the idea
that we're "locking data" and not "entering locked code" in mind.
Further, remove all additional "flags" previously passed to the
lock acquire/release routines with the exception of two:
MTX_QUIET and MTX_NOSWITCH
The functionality of these flags is preserved and they can be passed
to the lock/unlock routines by calling the corresponding wrappers:
mtx_{lock, unlock}_flags(lock, flag(s)) and
mtx_{lock, unlock}_spin_flags(lock, flag(s)) for MTX_DEF and MTX_SPIN
locks, respectively.
Re-inline some lock acq/rel code; in the sleep lock case, we only
inline the _obtain_lock()s in order to ensure that the inlined code
fits into a cache line. In the spin lock case, we inline recursion and
actually only perform a function call if we need to spin. This change
has been made with the idea that we generally tend to avoid spin locks
and that also the spin locks that we do have and are heavily used
(i.e. sched_lock) do recurse, and therefore in an effort to reduce
function call overhead for some architectures (such as alpha), we
inline recursion for this case.
Create a new malloc type for the witness code and retire from using
the M_DEV type. The new type is called M_WITNESS and is only declared
if WITNESS is enabled.
Begin cleaning up some machdep/mutex.h code - specifically updated the
"optimized" inlined code in alpha/mutex.h and wrote MTX_LOCK_SPIN
and MTX_UNLOCK_SPIN asm macros for the i386/mutex.h as we presently
need those.
Finally, caught up to the interface changes in all sys code.
Contributors: jake, jhb, jasone (in no particular order)
2001-02-09 06:11:45 +00:00
|
|
|
mtx_unlock(&mountlist_mtx);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change filesystem quotas.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct quotactl_args {
|
|
|
|
char *path;
|
|
|
|
int cmd;
|
|
|
|
int uid;
|
|
|
|
caddr_t arg;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_quotactl(struct thread *td, struct quotactl_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2007-03-14 08:45:55 +00:00
|
|
|
struct mount *mp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_CMD(uap->cmd);
|
|
|
|
AUDIT_ARG_UID(uap->uid);
|
2009-05-27 14:11:23 +00:00
|
|
|
if (!prison_allow(td->td_ucred, PR_ALLOW_QUOTAS))
|
This Implements the mumbled about "Jail" feature.
This is a seriously beefed up chroot kind of thing. The process
is jailed along the same lines as a chroot does it, but with
additional tough restrictions imposed on what the superuser can do.
For all I know, it is safe to hand over the root bit inside a
prison to the customer living in that prison, this is what
it was developed for in fact: "real virtual servers".
Each prison has an ip number associated with it, which all IP
communications will be coerced to use and each prison has its own
hostname.
Needless to say, you need more RAM this way, but the advantage is
that each customer can run their own particular version of apache
and not stomp on the toes of their neighbors.
It generally does what one would expect, but setting up a jail
still takes a little knowledge.
A few notes:
I have no scripts for setting up a jail, don't ask me for them.
The IP number should be an alias on one of the interfaces.
mount a /proc in each jail, it will make ps more useable.
/proc/<pid>/status tells the hostname of the prison for
jailed processes.
Quotas are only sensible if you have a mountpoint per prison.
There are no privisions for stopping resource-hogging.
Some "#ifdef INET" and similar may be missing (send patches!)
If somebody wants to take it from here and develop it into
more of a "virtual machine" they should be most welcome!
Tools, comments, patches & documentation most welcome.
Have fun...
Sponsored by: http://www.rndassociates.com/
Run for almost a year by: http://www.servetheweb.com/
1999-04-28 11:38:52 +00:00
|
|
|
return (EPERM);
|
2013-01-31 22:20:05 +00:00
|
|
|
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
|
|
|
|
uap->path, td);
|
2006-03-21 23:58:37 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2004-04-26 15:44:42 +00:00
|
|
|
mp = nd.ni_vp->v_mount;
|
2008-12-18 12:01:19 +00:00
|
|
|
vfs_ref(mp);
|
|
|
|
vput(nd.ni_vp);
|
|
|
|
error = vfs_busy(mp, 0);
|
|
|
|
vfs_rel(mp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2007-03-14 08:45:55 +00:00
|
|
|
return (error);
|
2009-05-11 15:33:26 +00:00
|
|
|
error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg);
|
2012-01-08 23:06:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Since quota on operation typically needs to open quota
|
|
|
|
* file, the Q_QUOTAON handler needs to unbusy the mount point
|
|
|
|
* before calling into namei. Otherwise, unmount might be
|
|
|
|
* started between two vfs_busy() invocations (first is our,
|
|
|
|
* second is from mount point cross-walk code in lookup()),
|
|
|
|
* causing deadlock.
|
|
|
|
*
|
|
|
|
* Require that Q_QUOTAON handles the vfs_busy() reference on
|
|
|
|
* its own, always returning with ubusied mount point.
|
|
|
|
*/
|
Fix state of dquot-less vnodes after failed quotaoff.
UFS quotaoff iterates over all mp vnodes, and derefences and clears
the pointers to corresponding dquots. If SU work items transiently
reference some of dquots,quotaoff() would eventually fail, but all
processed vnodes are already stripped from dquots. The state is
problematic, since quotas are left enabled, but there is no dquots
where blocks and inodes can be accounted. The result is assertion
failures and NULL pointer dereferences.
Fix it by suspending writes around quotaoff() call. Since the
filesystem is synced, no dandling references to dquots from SU
workitems can left behind, which means that quotaoff succeeds.
The complication there is that quotaoff VFS op is performed with the
mount point busied, while to suspend, we need to start write on the
mp. If vn_start_write() is called on busied mp, system might deadlock
against parallel unmount request. Handle this by unbusy-ing mp before
starting write, which in turn requires changing the quotaoff()
interface to return with the mount point not busied, same as was done
for quotaon().
Reviewed by: mckusick
Reported and tested by: pho
Sponsored by: The FreeBSD Foundation
Approved by: re (gjb)
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D17208
2018-09-19 14:36:57 +00:00
|
|
|
if ((uap->cmd >> SUBCMDSHIFT) != Q_QUOTAON &&
|
|
|
|
(uap->cmd >> SUBCMDSHIFT) != Q_QUOTAOFF)
|
2012-01-08 23:06:53 +00:00
|
|
|
vfs_unbusy(mp);
|
2000-07-11 22:07:57 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2007-08-28 20:28:12 +00:00
|
|
|
/*
|
|
|
|
* Used by statfs conversion routines to scale the block size up if
|
|
|
|
* necessary so that all of the block counts are <= 'max_size'. Note
|
|
|
|
* that 'max_size' should be a bitmask, i.e. 2^n - 1 for some non-zero
|
|
|
|
* value of 'n'.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
statfs_scale_blocks(struct statfs *sf, long max_size)
|
|
|
|
{
|
|
|
|
uint64_t count;
|
|
|
|
int shift;
|
|
|
|
|
|
|
|
KASSERT(powerof2(max_size + 1), ("%s: invalid max_size", __func__));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Attempt to scale the block counts to give a more accurate
|
|
|
|
* overview to userland of the ratio of free space to used
|
|
|
|
* space. To do this, find the largest block count and compute
|
|
|
|
* a divisor that lets it fit into a signed integer <= max_size.
|
|
|
|
*/
|
|
|
|
if (sf->f_bavail < 0)
|
|
|
|
count = -sf->f_bavail;
|
|
|
|
else
|
|
|
|
count = sf->f_bavail;
|
|
|
|
count = MAX(sf->f_blocks, MAX(sf->f_bfree, count));
|
|
|
|
if (count <= max_size)
|
|
|
|
return;
|
|
|
|
|
|
|
|
count >>= flsl(max_size);
|
|
|
|
shift = 0;
|
|
|
|
while (count > 0) {
|
|
|
|
shift++;
|
|
|
|
count >>=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sf->f_bsize <<= shift;
|
|
|
|
sf->f_blocks >>= shift;
|
|
|
|
sf->f_bfree >>= shift;
|
|
|
|
sf->f_bavail >>= shift;
|
|
|
|
}
|
|
|
|
|
2017-01-02 18:20:22 +00:00
|
|
|
static int
|
|
|
|
kern_do_statfs(struct thread *td, struct mount *mp, struct statfs *buf)
|
|
|
|
{
|
2017-01-02 18:59:23 +00:00
|
|
|
struct statfs *sp;
|
2017-01-02 18:20:22 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
if (mp == NULL)
|
|
|
|
return (EBADF);
|
|
|
|
error = vfs_busy(mp, 0);
|
|
|
|
vfs_rel(mp);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
#ifdef MAC
|
|
|
|
error = mac_mount_check_stat(td->td_ucred, mp);
|
|
|
|
if (error != 0)
|
|
|
|
goto out;
|
|
|
|
#endif
|
|
|
|
/*
|
|
|
|
* Set these in case the underlying filesystem fails to do so.
|
|
|
|
*/
|
|
|
|
sp = &mp->mnt_stat;
|
|
|
|
sp->f_version = STATFS_VERSION;
|
|
|
|
sp->f_namemax = NAME_MAX;
|
|
|
|
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
|
|
|
|
error = VFS_STATFS(mp, sp);
|
|
|
|
if (error != 0)
|
|
|
|
goto out;
|
2017-01-02 18:59:23 +00:00
|
|
|
*buf = *sp;
|
2017-01-02 18:20:22 +00:00
|
|
|
if (priv_check(td, PRIV_VFS_GENERATION)) {
|
2017-01-02 18:59:23 +00:00
|
|
|
buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0;
|
|
|
|
prison_enforce_statfs(td->td_ucred, mp, buf);
|
2017-01-02 18:20:22 +00:00
|
|
|
}
|
|
|
|
out:
|
|
|
|
vfs_unbusy(mp);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Get filesystem statistics.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct statfs_args {
|
|
|
|
char *path;
|
|
|
|
struct statfs *buf;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_statfs(struct thread *td, struct statfs_args *uap)
|
2005-02-07 18:44:55 +00:00
|
|
|
{
|
2017-01-05 17:19:26 +00:00
|
|
|
struct statfs *sfp;
|
2005-02-07 18:44:55 +00:00
|
|
|
int error;
|
|
|
|
|
2017-01-05 17:19:26 +00:00
|
|
|
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
|
|
|
|
error = kern_statfs(td, uap->path, UIO_USERSPACE, sfp);
|
2005-02-07 18:44:55 +00:00
|
|
|
if (error == 0)
|
2017-01-05 17:19:26 +00:00
|
|
|
error = copyout(sfp, uap->buf, sizeof(struct statfs));
|
|
|
|
free(sfp, M_STATFS);
|
2005-02-07 18:44:55 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_statfs(struct thread *td, const char *path, enum uio_seg pathseg,
|
2005-02-07 18:44:55 +00:00
|
|
|
struct statfs *buf)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2003-11-12 08:01:40 +00:00
|
|
|
struct mount *mp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2013-01-31 22:20:05 +00:00
|
|
|
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
|
|
|
|
pathseg, path, td);
|
2005-05-27 19:15:46 +00:00
|
|
|
error = namei(&nd);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
mp = nd.ni_vp->v_mount;
|
2006-02-23 05:18:07 +00:00
|
|
|
vfs_ref(mp);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2006-02-23 05:18:07 +00:00
|
|
|
vput(nd.ni_vp);
|
2017-01-02 18:20:22 +00:00
|
|
|
return (kern_do_statfs(td, mp, buf));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get filesystem statistics.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct fstatfs_args {
|
|
|
|
int fd;
|
|
|
|
struct statfs *buf;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_fstatfs(struct thread *td, struct fstatfs_args *uap)
|
2005-02-07 18:44:55 +00:00
|
|
|
{
|
2017-01-05 17:19:26 +00:00
|
|
|
struct statfs *sfp;
|
2005-02-07 18:44:55 +00:00
|
|
|
int error;
|
|
|
|
|
2017-01-05 17:19:26 +00:00
|
|
|
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
|
|
|
|
error = kern_fstatfs(td, uap->fd, sfp);
|
2005-02-07 18:44:55 +00:00
|
|
|
if (error == 0)
|
2017-01-05 17:19:26 +00:00
|
|
|
error = copyout(sfp, uap->buf, sizeof(struct statfs));
|
|
|
|
free(sfp, M_STATFS);
|
2005-02-07 18:44:55 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct file *fp;
|
|
|
|
struct mount *mp;
|
2006-02-06 10:15:27 +00:00
|
|
|
struct vnode *vp;
|
1994-05-24 10:09:53 +00:00
|
|
|
int error;
|
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_FD(fd);
|
2018-05-20 05:13:12 +00:00
|
|
|
error = getvnode(td, fd, &cap_fstatfs_rights, &fp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2006-02-06 10:15:27 +00:00
|
|
|
vp = fp->f_vnode;
|
Use shared vnode locks instead of exclusive vnode locks for the access(),
chdir(), chroot(), eaccess(), fpathconf(), fstat(), fstatfs(), lseek()
(when figuring out the current size of the file in the SEEK_END case),
pathconf(), readlink(), and statfs() system calls.
Submitted by: ups (mostly)
Tested by: pho
MFC after: 1 month
2008-11-03 20:31:00 +00:00
|
|
|
vn_lock(vp, LK_SHARED | LK_RETRY);
|
2006-02-23 05:18:07 +00:00
|
|
|
#ifdef AUDIT
|
2009-07-28 21:52:24 +00:00
|
|
|
AUDIT_ARG_VNODE1(vp);
|
Add pathname and/or vnode argument auditing for the following system calls:
quotactl, statfs, fstatfs, fchdir, chdir, chroot, open, mknod, mkfifo,
link, symlink, undelete, unlink, access, eaccess, stat, lstat, pathconf,
readlink, chflags, lchflags, fchflags, chmod, lchmod, fchmod, chown,
lchown, fchown, utimes, lutimes, futimes, truncate, ftruncate, fsync,
rename, mkdir, rmdir, getdirentries, revoke, lgetfh, getfh, extattrctl,
extattr_set_file, extattr_set_link, extattr_get_file, extattr_get_link,
extattr_delete_file, extattr_delete_link, extattr_list_file, extattr_list_link.
In many cases the pathname and vnode auditing is done within namei lookup
instead of directly in the system call.
Audit the remaining arguments to these system calls:
fstatfs, fchdir, open, mknod, chflags, lchflags, fchflags, chmod, lchmod,
fchmod, chown, lchown, fchown, futimes, ftruncate, fsync, mkdir,
getdirentries.
2006-02-22 16:04:20 +00:00
|
|
|
#endif
|
2006-02-22 09:52:25 +00:00
|
|
|
mp = vp->v_mount;
|
2017-01-02 18:49:48 +00:00
|
|
|
if (mp != NULL)
|
2006-02-23 05:18:07 +00:00
|
|
|
vfs_ref(mp);
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2002-01-13 11:58:06 +00:00
|
|
|
fdrop(fp, td);
|
2017-01-02 18:20:22 +00:00
|
|
|
return (kern_do_statfs(td, mp, buf));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get statistics on all filesystems.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct getfsstat_args {
|
|
|
|
struct statfs *buf;
|
|
|
|
long bufsize;
|
2016-12-27 20:21:11 +00:00
|
|
|
int mode;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_getfsstat(struct thread *td, struct getfsstat_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2015-04-15 09:13:11 +00:00
|
|
|
size_t count;
|
|
|
|
int error;
|
2005-06-09 17:44:46 +00:00
|
|
|
|
2015-11-20 14:08:12 +00:00
|
|
|
if (uap->bufsize < 0 || uap->bufsize > SIZE_MAX)
|
|
|
|
return (EINVAL);
|
2015-04-15 09:13:11 +00:00
|
|
|
error = kern_getfsstat(td, &uap->buf, uap->bufsize, &count,
|
2016-12-27 20:21:11 +00:00
|
|
|
UIO_USERSPACE, uap->mode);
|
2015-04-15 09:13:11 +00:00
|
|
|
if (error == 0)
|
|
|
|
td->td_retval[0] = count;
|
|
|
|
return (error);
|
2005-06-09 17:44:46 +00:00
|
|
|
}
|
|
|
|
|
2005-06-11 14:58:20 +00:00
|
|
|
/*
|
|
|
|
* If (bufsize > 0 && bufseg == UIO_SYSSPACE)
|
2013-03-16 22:37:30 +00:00
|
|
|
* The caller is responsible for freeing memory which will be allocated
|
2005-06-11 14:58:20 +00:00
|
|
|
* in '*buf'.
|
|
|
|
*/
|
2005-06-09 17:44:46 +00:00
|
|
|
int
|
2005-06-11 14:58:20 +00:00
|
|
|
kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
|
2016-12-27 20:21:11 +00:00
|
|
|
size_t *countp, enum uio_seg bufseg, int mode)
|
2005-06-09 17:44:46 +00:00
|
|
|
{
|
2003-11-12 08:01:40 +00:00
|
|
|
struct mount *mp, *nmp;
|
2017-01-05 17:19:26 +00:00
|
|
|
struct statfs *sfsp, *sp, *sptmp, *tofree;
|
2005-06-09 17:44:46 +00:00
|
|
|
size_t count, maxcount;
|
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2016-12-27 20:21:11 +00:00
|
|
|
switch (mode) {
|
|
|
|
case MNT_WAIT:
|
|
|
|
case MNT_NOWAIT:
|
|
|
|
break;
|
|
|
|
default:
|
2017-01-04 16:09:45 +00:00
|
|
|
if (bufseg == UIO_SYSSPACE)
|
|
|
|
*buf = NULL;
|
2016-12-27 20:21:11 +00:00
|
|
|
return (EINVAL);
|
|
|
|
}
|
2016-11-02 09:43:19 +00:00
|
|
|
restart:
|
2005-06-09 17:44:46 +00:00
|
|
|
maxcount = bufsize / sizeof(struct statfs);
|
2016-11-02 09:43:19 +00:00
|
|
|
if (bufsize == 0) {
|
2005-06-11 14:58:20 +00:00
|
|
|
sfsp = NULL;
|
2016-11-02 09:43:19 +00:00
|
|
|
tofree = NULL;
|
|
|
|
} else if (bufseg == UIO_USERSPACE) {
|
2005-06-11 14:58:20 +00:00
|
|
|
sfsp = *buf;
|
2016-11-02 09:43:19 +00:00
|
|
|
tofree = NULL;
|
|
|
|
} else /* if (bufseg == UIO_SYSSPACE) */ {
|
2005-06-11 14:58:20 +00:00
|
|
|
count = 0;
|
2005-06-12 07:03:23 +00:00
|
|
|
mtx_lock(&mountlist_mtx);
|
2005-06-11 14:58:20 +00:00
|
|
|
TAILQ_FOREACH(mp, &mountlist, mnt_list) {
|
|
|
|
count++;
|
|
|
|
}
|
2005-06-12 07:03:23 +00:00
|
|
|
mtx_unlock(&mountlist_mtx);
|
2005-06-11 14:58:20 +00:00
|
|
|
if (maxcount > count)
|
|
|
|
maxcount = count;
|
2016-11-02 09:43:19 +00:00
|
|
|
tofree = sfsp = *buf = malloc(maxcount * sizeof(struct statfs),
|
2017-01-05 17:19:26 +00:00
|
|
|
M_STATFS, M_WAITOK);
|
2005-06-11 14:58:20 +00:00
|
|
|
}
|
|
|
|
count = 0;
|
2005-06-12 07:03:23 +00:00
|
|
|
mtx_lock(&mountlist_mtx);
|
1999-11-20 10:00:46 +00:00
|
|
|
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
|
2005-06-09 18:49:19 +00:00
|
|
|
if (prison_canseemount(td->td_ucred, mp) != 0) {
|
2004-02-14 18:31:11 +00:00
|
|
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
|
|
|
continue;
|
|
|
|
}
|
2002-07-31 01:27:33 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
if (mac_mount_check_stat(td->td_ucred, mp) != 0) {
|
2002-07-31 01:27:33 +00:00
|
|
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
2016-12-27 20:21:11 +00:00
|
|
|
if (mode == MNT_WAIT) {
|
2016-11-02 09:43:19 +00:00
|
|
|
if (vfs_busy(mp, MBF_MNTLSTLOCK) != 0) {
|
|
|
|
/*
|
|
|
|
* If vfs_busy() failed, and MBF_NOWAIT
|
|
|
|
* wasn't passed, then the mp is gone.
|
|
|
|
* Furthermore, because of MBF_MNTLSTLOCK,
|
|
|
|
* the mountlist_mtx was dropped. We have
|
|
|
|
* no other choice than to start over.
|
|
|
|
*/
|
|
|
|
mtx_unlock(&mountlist_mtx);
|
2017-01-05 17:19:26 +00:00
|
|
|
free(tofree, M_STATFS);
|
2016-11-02 09:43:19 +00:00
|
|
|
goto restart;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (vfs_busy(mp, MBF_NOWAIT | MBF_MNTLSTLOCK) != 0) {
|
|
|
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
|
|
|
continue;
|
|
|
|
}
|
1996-01-16 13:07:14 +00:00
|
|
|
}
|
2017-01-05 17:03:35 +00:00
|
|
|
if (sfsp != NULL && count < maxcount) {
|
1994-05-24 10:09:53 +00:00
|
|
|
sp = &mp->mnt_stat;
|
2003-11-12 08:01:40 +00:00
|
|
|
/*
|
|
|
|
* Set these in case the underlying filesystem
|
|
|
|
* fails to do so.
|
|
|
|
*/
|
|
|
|
sp->f_version = STATFS_VERSION;
|
|
|
|
sp->f_namemax = NAME_MAX;
|
|
|
|
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2016-12-27 20:21:11 +00:00
|
|
|
* If MNT_NOWAIT is specified, do not refresh
|
|
|
|
* the fsstat cache.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2016-12-27 20:21:11 +00:00
|
|
|
if (mode != MNT_NOWAIT) {
|
2016-10-29 12:38:30 +00:00
|
|
|
error = VFS_STATFS(mp, sp);
|
|
|
|
if (error != 0) {
|
|
|
|
mtx_lock(&mountlist_mtx);
|
|
|
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
|
|
|
vfs_unbusy(mp);
|
|
|
|
continue;
|
|
|
|
}
|
1996-01-16 13:07:14 +00:00
|
|
|
}
|
2006-11-06 13:42:10 +00:00
|
|
|
if (priv_check(td, PRIV_VFS_GENERATION)) {
|
2017-01-05 17:19:26 +00:00
|
|
|
sptmp = malloc(sizeof(struct statfs), M_STATFS,
|
|
|
|
M_WAITOK);
|
|
|
|
*sptmp = *sp;
|
|
|
|
sptmp->f_fsid.val[0] = sptmp->f_fsid.val[1] = 0;
|
|
|
|
prison_enforce_statfs(td->td_ucred, mp, sptmp);
|
|
|
|
sp = sptmp;
|
|
|
|
} else
|
|
|
|
sptmp = NULL;
|
|
|
|
if (bufseg == UIO_SYSSPACE) {
|
2005-06-11 14:58:20 +00:00
|
|
|
bcopy(sp, sfsp, sizeof(*sp));
|
2017-01-05 17:19:26 +00:00
|
|
|
free(sptmp, M_STATFS);
|
|
|
|
} else /* if (bufseg == UIO_USERSPACE) */ {
|
2005-06-09 17:44:46 +00:00
|
|
|
error = copyout(sp, sfsp, sizeof(*sp));
|
2017-01-05 17:19:26 +00:00
|
|
|
free(sptmp, M_STATFS);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0) {
|
2008-08-31 14:26:08 +00:00
|
|
|
vfs_unbusy(mp);
|
2005-06-09 17:44:46 +00:00
|
|
|
return (error);
|
|
|
|
}
|
2005-06-11 14:58:20 +00:00
|
|
|
}
|
2005-06-09 17:44:46 +00:00
|
|
|
sfsp++;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
count++;
|
Change and clean the mutex lock interface.
mtx_enter(lock, type) becomes:
mtx_lock(lock) for sleep locks (MTX_DEF-initialized locks)
mtx_lock_spin(lock) for spin locks (MTX_SPIN-initialized)
similarily, for releasing a lock, we now have:
mtx_unlock(lock) for MTX_DEF and mtx_unlock_spin(lock) for MTX_SPIN.
We change the caller interface for the two different types of locks
because the semantics are entirely different for each case, and this
makes it explicitly clear and, at the same time, it rids us of the
extra `type' argument.
The enter->lock and exit->unlock change has been made with the idea
that we're "locking data" and not "entering locked code" in mind.
Further, remove all additional "flags" previously passed to the
lock acquire/release routines with the exception of two:
MTX_QUIET and MTX_NOSWITCH
The functionality of these flags is preserved and they can be passed
to the lock/unlock routines by calling the corresponding wrappers:
mtx_{lock, unlock}_flags(lock, flag(s)) and
mtx_{lock, unlock}_spin_flags(lock, flag(s)) for MTX_DEF and MTX_SPIN
locks, respectively.
Re-inline some lock acq/rel code; in the sleep lock case, we only
inline the _obtain_lock()s in order to ensure that the inlined code
fits into a cache line. In the spin lock case, we inline recursion and
actually only perform a function call if we need to spin. This change
has been made with the idea that we generally tend to avoid spin locks
and that also the spin locks that we do have and are heavily used
(i.e. sched_lock) do recurse, and therefore in an effort to reduce
function call overhead for some architectures (such as alpha), we
inline recursion for this case.
Create a new malloc type for the witness code and retire from using
the M_DEV type. The new type is called M_WITNESS and is only declared
if WITNESS is enabled.
Begin cleaning up some machdep/mutex.h code - specifically updated the
"optimized" inlined code in alpha/mutex.h and wrote MTX_LOCK_SPIN
and MTX_UNLOCK_SPIN asm macros for the i386/mutex.h as we presently
need those.
Finally, caught up to the interface changes in all sys code.
Contributors: jake, jhb, jasone (in no particular order)
2001-02-09 06:11:45 +00:00
|
|
|
mtx_lock(&mountlist_mtx);
|
1999-11-20 10:00:46 +00:00
|
|
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
2008-08-31 14:26:08 +00:00
|
|
|
vfs_unbusy(mp);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
Change and clean the mutex lock interface.
mtx_enter(lock, type) becomes:
mtx_lock(lock) for sleep locks (MTX_DEF-initialized locks)
mtx_lock_spin(lock) for spin locks (MTX_SPIN-initialized)
similarily, for releasing a lock, we now have:
mtx_unlock(lock) for MTX_DEF and mtx_unlock_spin(lock) for MTX_SPIN.
We change the caller interface for the two different types of locks
because the semantics are entirely different for each case, and this
makes it explicitly clear and, at the same time, it rids us of the
extra `type' argument.
The enter->lock and exit->unlock change has been made with the idea
that we're "locking data" and not "entering locked code" in mind.
Further, remove all additional "flags" previously passed to the
lock acquire/release routines with the exception of two:
MTX_QUIET and MTX_NOSWITCH
The functionality of these flags is preserved and they can be passed
to the lock/unlock routines by calling the corresponding wrappers:
mtx_{lock, unlock}_flags(lock, flag(s)) and
mtx_{lock, unlock}_spin_flags(lock, flag(s)) for MTX_DEF and MTX_SPIN
locks, respectively.
Re-inline some lock acq/rel code; in the sleep lock case, we only
inline the _obtain_lock()s in order to ensure that the inlined code
fits into a cache line. In the spin lock case, we inline recursion and
actually only perform a function call if we need to spin. This change
has been made with the idea that we generally tend to avoid spin locks
and that also the spin locks that we do have and are heavily used
(i.e. sched_lock) do recurse, and therefore in an effort to reduce
function call overhead for some architectures (such as alpha), we
inline recursion for this case.
Create a new malloc type for the witness code and retire from using
the M_DEV type. The new type is called M_WITNESS and is only declared
if WITNESS is enabled.
Begin cleaning up some machdep/mutex.h code - specifically updated the
"optimized" inlined code in alpha/mutex.h and wrote MTX_LOCK_SPIN
and MTX_UNLOCK_SPIN asm macros for the i386/mutex.h as we presently
need those.
Finally, caught up to the interface changes in all sys code.
Contributors: jake, jhb, jasone (in no particular order)
2001-02-09 06:11:45 +00:00
|
|
|
mtx_unlock(&mountlist_mtx);
|
2017-01-05 17:03:35 +00:00
|
|
|
if (sfsp != NULL && count > maxcount)
|
2015-04-15 09:13:11 +00:00
|
|
|
*countp = maxcount;
|
1994-05-24 10:09:53 +00:00
|
|
|
else
|
2015-04-15 09:13:11 +00:00
|
|
|
*countp = count;
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2003-11-12 08:01:40 +00:00
|
|
|
#ifdef COMPAT_FREEBSD4
|
|
|
|
/*
|
|
|
|
* Get old format filesystem statistics.
|
|
|
|
*/
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
static void freebsd4_cvtstatfs(struct statfs *, struct ostatfs *);
|
2003-11-12 08:01:40 +00:00
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct freebsd4_statfs_args {
|
|
|
|
char *path;
|
|
|
|
struct ostatfs *buf;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
freebsd4_statfs(struct thread *td, struct freebsd4_statfs_args *uap)
|
2003-11-12 08:01:40 +00:00
|
|
|
{
|
|
|
|
struct ostatfs osb;
|
2017-01-05 17:19:26 +00:00
|
|
|
struct statfs *sfp;
|
2003-11-12 08:01:40 +00:00
|
|
|
int error;
|
|
|
|
|
2017-01-05 17:19:26 +00:00
|
|
|
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
|
|
|
|
error = kern_statfs(td, uap->path, UIO_USERSPACE, sfp);
|
|
|
|
if (error == 0) {
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd4_cvtstatfs(sfp, &osb);
|
2017-01-05 17:19:26 +00:00
|
|
|
error = copyout(&osb, uap->buf, sizeof(osb));
|
|
|
|
}
|
|
|
|
free(sfp, M_STATFS);
|
|
|
|
return (error);
|
2003-11-12 08:01:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get filesystem statistics.
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct freebsd4_fstatfs_args {
|
|
|
|
int fd;
|
|
|
|
struct ostatfs *buf;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
freebsd4_fstatfs(struct thread *td, struct freebsd4_fstatfs_args *uap)
|
2003-11-12 08:01:40 +00:00
|
|
|
{
|
|
|
|
struct ostatfs osb;
|
2017-01-05 17:19:26 +00:00
|
|
|
struct statfs *sfp;
|
2003-11-12 08:01:40 +00:00
|
|
|
int error;
|
|
|
|
|
2017-01-05 17:19:26 +00:00
|
|
|
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
|
|
|
|
error = kern_fstatfs(td, uap->fd, sfp);
|
|
|
|
if (error == 0) {
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd4_cvtstatfs(sfp, &osb);
|
2017-01-05 17:19:26 +00:00
|
|
|
error = copyout(&osb, uap->buf, sizeof(osb));
|
|
|
|
}
|
|
|
|
free(sfp, M_STATFS);
|
|
|
|
return (error);
|
2003-11-12 08:01:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get statistics on all filesystems.
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct freebsd4_getfsstat_args {
|
|
|
|
struct ostatfs *buf;
|
|
|
|
long bufsize;
|
2016-12-27 20:21:11 +00:00
|
|
|
int mode;
|
2003-11-12 08:01:40 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
freebsd4_getfsstat(struct thread *td, struct freebsd4_getfsstat_args *uap)
|
2003-11-12 08:01:40 +00:00
|
|
|
{
|
2005-06-09 17:44:46 +00:00
|
|
|
struct statfs *buf, *sp;
|
2003-11-12 08:01:40 +00:00
|
|
|
struct ostatfs osb;
|
2005-06-09 17:44:46 +00:00
|
|
|
size_t count, size;
|
|
|
|
int error;
|
2003-11-12 08:01:40 +00:00
|
|
|
|
2015-11-20 14:08:12 +00:00
|
|
|
if (uap->bufsize < 0)
|
|
|
|
return (EINVAL);
|
2005-06-09 17:44:46 +00:00
|
|
|
count = uap->bufsize / sizeof(struct ostatfs);
|
2015-11-20 14:08:12 +00:00
|
|
|
if (count > SIZE_MAX / sizeof(struct statfs))
|
|
|
|
return (EINVAL);
|
2005-06-09 17:44:46 +00:00
|
|
|
size = count * sizeof(struct statfs);
|
2015-04-15 09:13:11 +00:00
|
|
|
error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE,
|
2016-12-27 20:21:11 +00:00
|
|
|
uap->mode);
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
if (error == 0)
|
|
|
|
td->td_retval[0] = count;
|
2015-11-20 14:08:12 +00:00
|
|
|
if (size != 0) {
|
2005-06-09 17:44:46 +00:00
|
|
|
sp = buf;
|
2015-11-20 14:08:12 +00:00
|
|
|
while (count != 0 && error == 0) {
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd4_cvtstatfs(sp, &osb);
|
2005-06-09 17:44:46 +00:00
|
|
|
error = copyout(&osb, uap->buf, sizeof(osb));
|
|
|
|
sp++;
|
|
|
|
uap->buf++;
|
|
|
|
count--;
|
2003-11-12 08:01:40 +00:00
|
|
|
}
|
2017-01-05 17:19:26 +00:00
|
|
|
free(buf, M_STATFS);
|
2003-11-12 08:01:40 +00:00
|
|
|
}
|
2005-06-09 17:44:46 +00:00
|
|
|
return (error);
|
2003-11-12 08:01:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Implement fstatfs() for (NFS) file handles.
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct freebsd4_fhstatfs_args {
|
|
|
|
struct fhandle *u_fhp;
|
|
|
|
struct ostatfs *buf;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
freebsd4_fhstatfs(struct thread *td, struct freebsd4_fhstatfs_args *uap)
|
2003-11-12 08:01:40 +00:00
|
|
|
{
|
|
|
|
struct ostatfs osb;
|
2017-01-05 17:19:26 +00:00
|
|
|
struct statfs *sfp;
|
2003-11-12 08:01:40 +00:00
|
|
|
fhandle_t fh;
|
|
|
|
int error;
|
|
|
|
|
2005-05-27 19:15:46 +00:00
|
|
|
error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2003-11-12 08:01:40 +00:00
|
|
|
return (error);
|
2017-01-05 17:19:26 +00:00
|
|
|
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
|
|
|
|
error = kern_fhstatfs(td, fh, sfp);
|
|
|
|
if (error == 0) {
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd4_cvtstatfs(sfp, &osb);
|
2017-01-05 17:19:26 +00:00
|
|
|
error = copyout(&osb, uap->buf, sizeof(osb));
|
|
|
|
}
|
|
|
|
free(sfp, M_STATFS);
|
|
|
|
return (error);
|
2003-11-12 08:01:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert a new format statfs structure to an old format statfs structure.
|
|
|
|
*/
|
|
|
|
static void
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd4_cvtstatfs(struct statfs *nsp, struct ostatfs *osp)
|
2003-11-12 08:01:40 +00:00
|
|
|
{
|
|
|
|
|
2007-08-28 20:28:12 +00:00
|
|
|
statfs_scale_blocks(nsp, LONG_MAX);
|
2003-11-12 08:01:40 +00:00
|
|
|
bzero(osp, sizeof(*osp));
|
2007-08-28 20:28:12 +00:00
|
|
|
osp->f_bsize = nsp->f_bsize;
|
2003-11-12 08:01:40 +00:00
|
|
|
osp->f_iosize = MIN(nsp->f_iosize, LONG_MAX);
|
2007-08-28 20:28:12 +00:00
|
|
|
osp->f_blocks = nsp->f_blocks;
|
|
|
|
osp->f_bfree = nsp->f_bfree;
|
|
|
|
osp->f_bavail = nsp->f_bavail;
|
2003-11-12 08:01:40 +00:00
|
|
|
osp->f_files = MIN(nsp->f_files, LONG_MAX);
|
|
|
|
osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX);
|
|
|
|
osp->f_owner = nsp->f_owner;
|
|
|
|
osp->f_type = nsp->f_type;
|
|
|
|
osp->f_flags = nsp->f_flags;
|
|
|
|
osp->f_syncwrites = MIN(nsp->f_syncwrites, LONG_MAX);
|
|
|
|
osp->f_asyncwrites = MIN(nsp->f_asyncwrites, LONG_MAX);
|
|
|
|
osp->f_syncreads = MIN(nsp->f_syncreads, LONG_MAX);
|
|
|
|
osp->f_asyncreads = MIN(nsp->f_asyncreads, LONG_MAX);
|
2006-03-04 00:09:09 +00:00
|
|
|
strlcpy(osp->f_fstypename, nsp->f_fstypename,
|
|
|
|
MIN(MFSNAMELEN, OMFSNAMELEN));
|
|
|
|
strlcpy(osp->f_mntonname, nsp->f_mntonname,
|
2006-03-03 07:20:54 +00:00
|
|
|
MIN(MNAMELEN, OMNAMELEN));
|
2006-03-04 00:09:09 +00:00
|
|
|
strlcpy(osp->f_mntfromname, nsp->f_mntfromname,
|
2006-03-03 07:20:54 +00:00
|
|
|
MIN(MNAMELEN, OMNAMELEN));
|
2005-05-22 21:52:30 +00:00
|
|
|
osp->f_fsid = nsp->f_fsid;
|
2003-11-12 08:01:40 +00:00
|
|
|
}
|
|
|
|
#endif /* COMPAT_FREEBSD4 */
|
|
|
|
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
#if defined(COMPAT_FREEBSD11)
|
|
|
|
/*
|
|
|
|
* Get old format filesystem statistics.
|
|
|
|
*/
|
|
|
|
static void freebsd11_cvtstatfs(struct statfs *, struct freebsd11_statfs *);
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd11_statfs(struct thread *td, struct freebsd11_statfs_args *uap)
|
|
|
|
{
|
|
|
|
struct freebsd11_statfs osb;
|
|
|
|
struct statfs *sfp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
|
|
|
|
error = kern_statfs(td, uap->path, UIO_USERSPACE, sfp);
|
|
|
|
if (error == 0) {
|
|
|
|
freebsd11_cvtstatfs(sfp, &osb);
|
|
|
|
error = copyout(&osb, uap->buf, sizeof(osb));
|
|
|
|
}
|
|
|
|
free(sfp, M_STATFS);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get filesystem statistics.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
freebsd11_fstatfs(struct thread *td, struct freebsd11_fstatfs_args *uap)
|
|
|
|
{
|
|
|
|
struct freebsd11_statfs osb;
|
|
|
|
struct statfs *sfp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
|
|
|
|
error = kern_fstatfs(td, uap->fd, sfp);
|
|
|
|
if (error == 0) {
|
|
|
|
freebsd11_cvtstatfs(sfp, &osb);
|
|
|
|
error = copyout(&osb, uap->buf, sizeof(osb));
|
|
|
|
}
|
|
|
|
free(sfp, M_STATFS);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get statistics on all filesystems.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
freebsd11_getfsstat(struct thread *td, struct freebsd11_getfsstat_args *uap)
|
|
|
|
{
|
|
|
|
struct freebsd11_statfs osb;
|
|
|
|
struct statfs *buf, *sp;
|
|
|
|
size_t count, size;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
count = uap->bufsize / sizeof(struct ostatfs);
|
|
|
|
size = count * sizeof(struct statfs);
|
|
|
|
error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE,
|
|
|
|
uap->mode);
|
|
|
|
if (error == 0)
|
|
|
|
td->td_retval[0] = count;
|
|
|
|
if (size > 0) {
|
|
|
|
sp = buf;
|
|
|
|
while (count > 0 && error == 0) {
|
|
|
|
freebsd11_cvtstatfs(sp, &osb);
|
|
|
|
error = copyout(&osb, uap->buf, sizeof(osb));
|
|
|
|
sp++;
|
|
|
|
uap->buf++;
|
|
|
|
count--;
|
|
|
|
}
|
|
|
|
free(buf, M_STATFS);
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Implement fstatfs() for (NFS) file handles.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
freebsd11_fhstatfs(struct thread *td, struct freebsd11_fhstatfs_args *uap)
|
|
|
|
{
|
|
|
|
struct freebsd11_statfs osb;
|
|
|
|
struct statfs *sfp;
|
|
|
|
fhandle_t fh;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
|
|
|
|
error = kern_fhstatfs(td, fh, sfp);
|
|
|
|
if (error == 0) {
|
|
|
|
freebsd11_cvtstatfs(sfp, &osb);
|
|
|
|
error = copyout(&osb, uap->buf, sizeof(osb));
|
|
|
|
}
|
|
|
|
free(sfp, M_STATFS);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert a new format statfs structure to an old format statfs structure.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
freebsd11_cvtstatfs(struct statfs *nsp, struct freebsd11_statfs *osp)
|
|
|
|
{
|
|
|
|
|
|
|
|
bzero(osp, sizeof(*osp));
|
|
|
|
osp->f_version = FREEBSD11_STATFS_VERSION;
|
|
|
|
osp->f_type = nsp->f_type;
|
|
|
|
osp->f_flags = nsp->f_flags;
|
|
|
|
osp->f_bsize = nsp->f_bsize;
|
|
|
|
osp->f_iosize = nsp->f_iosize;
|
|
|
|
osp->f_blocks = nsp->f_blocks;
|
|
|
|
osp->f_bfree = nsp->f_bfree;
|
|
|
|
osp->f_bavail = nsp->f_bavail;
|
|
|
|
osp->f_files = nsp->f_files;
|
|
|
|
osp->f_ffree = nsp->f_ffree;
|
|
|
|
osp->f_syncwrites = nsp->f_syncwrites;
|
|
|
|
osp->f_asyncwrites = nsp->f_asyncwrites;
|
|
|
|
osp->f_syncreads = nsp->f_syncreads;
|
|
|
|
osp->f_asyncreads = nsp->f_asyncreads;
|
|
|
|
osp->f_namemax = nsp->f_namemax;
|
|
|
|
osp->f_owner = nsp->f_owner;
|
|
|
|
osp->f_fsid = nsp->f_fsid;
|
|
|
|
strlcpy(osp->f_fstypename, nsp->f_fstypename,
|
|
|
|
MIN(MFSNAMELEN, sizeof(osp->f_fstypename)));
|
|
|
|
strlcpy(osp->f_mntonname, nsp->f_mntonname,
|
|
|
|
MIN(MNAMELEN, sizeof(osp->f_mntonname)));
|
|
|
|
strlcpy(osp->f_mntfromname, nsp->f_mntfromname,
|
|
|
|
MIN(MNAMELEN, sizeof(osp->f_mntfromname)));
|
|
|
|
}
|
|
|
|
#endif /* COMPAT_FREEBSD11 */
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Change current working directory to a given file descriptor.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct fchdir_args {
|
|
|
|
int fd;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_fchdir(struct thread *td, struct fchdir_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2015-07-11 16:19:11 +00:00
|
|
|
struct vnode *vp, *tdp;
|
1997-02-10 02:22:35 +00:00
|
|
|
struct mount *mp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct file *fp;
|
|
|
|
int error;
|
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_FD(uap->fd);
|
2018-05-09 18:47:24 +00:00
|
|
|
error = getvnode(td, uap->fd, &cap_fchdir_rights,
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
&fp);
|
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2003-06-22 08:41:43 +00:00
|
|
|
vp = fp->f_vnode;
|
2016-12-12 19:16:35 +00:00
|
|
|
vrefact(vp);
|
2002-01-13 11:58:06 +00:00
|
|
|
fdrop(fp, td);
|
2009-01-23 22:13:30 +00:00
|
|
|
vn_lock(vp, LK_SHARED | LK_RETRY);
|
2009-07-28 21:52:24 +00:00
|
|
|
AUDIT_ARG_VNODE1(vp);
|
2006-07-19 18:30:33 +00:00
|
|
|
error = change_dir(vp, td);
|
1997-02-10 02:22:35 +00:00
|
|
|
while (!error && (mp = vp->v_mountedhere) != NULL) {
|
2008-11-02 10:15:42 +00:00
|
|
|
if (vfs_busy(mp, 0))
|
1997-02-10 02:22:35 +00:00
|
|
|
continue;
|
2009-05-11 15:33:26 +00:00
|
|
|
error = VFS_ROOT(mp, LK_SHARED, &tdp);
|
2008-08-31 14:26:08 +00:00
|
|
|
vfs_unbusy(mp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1997-02-10 02:22:35 +00:00
|
|
|
break;
|
|
|
|
vput(vp);
|
|
|
|
vp = tdp;
|
|
|
|
}
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0) {
|
1997-02-10 02:22:35 +00:00
|
|
|
vput(vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2015-07-11 16:19:11 +00:00
|
|
|
pwd_chdir(td, vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change current working directory (``.'').
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct chdir_args {
|
|
|
|
char *path;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_chdir(struct thread *td, struct chdir_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_chdir(td, uap->path, UIO_USERSPACE));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_chdir(struct thread *td, const char *path, enum uio_seg pathseg)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2012-10-22 17:50:54 +00:00
|
|
|
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
|
|
|
|
pathseg, path, td);
|
2003-04-09 02:55:18 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
|
|
|
return (error);
|
|
|
|
if ((error = change_dir(nd.ni_vp, td)) != 0) {
|
|
|
|
vput(nd.ni_vp);
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2003-04-09 02:55:18 +00:00
|
|
|
}
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(nd.ni_vp, 0);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2015-07-11 16:19:11 +00:00
|
|
|
pwd_chdir(td, nd.ni_vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change notion of root (``/'') directory.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct chroot_args {
|
|
|
|
char *path;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_chroot(struct thread *td, struct chroot_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2007-06-12 00:12:01 +00:00
|
|
|
error = priv_check(td, PRIV_VFS_CHROOT);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2013-01-31 22:20:05 +00:00
|
|
|
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
|
|
|
|
UIO_USERSPACE, uap->path, td);
|
2003-04-09 02:55:18 +00:00
|
|
|
error = namei(&nd);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2002-07-13 04:07:12 +00:00
|
|
|
goto error;
|
2013-09-05 00:19:30 +00:00
|
|
|
error = change_dir(nd.ni_vp, td);
|
|
|
|
if (error != 0)
|
2003-04-09 02:55:18 +00:00
|
|
|
goto e_vunlock;
|
2002-08-01 03:50:08 +00:00
|
|
|
#ifdef MAC
|
2013-09-05 00:19:30 +00:00
|
|
|
error = mac_vnode_check_chroot(td->td_ucred, nd.ni_vp);
|
|
|
|
if (error != 0)
|
2003-04-09 02:55:18 +00:00
|
|
|
goto e_vunlock;
|
2002-08-01 03:50:08 +00:00
|
|
|
#endif
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(nd.ni_vp, 0);
|
2015-07-11 16:19:11 +00:00
|
|
|
error = pwd_chroot(td, nd.ni_vp);
|
2003-04-09 02:55:18 +00:00
|
|
|
vrele(nd.ni_vp);
|
2002-07-13 04:07:12 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2003-04-09 02:55:18 +00:00
|
|
|
return (error);
|
|
|
|
e_vunlock:
|
|
|
|
vput(nd.ni_vp);
|
2002-07-13 04:07:12 +00:00
|
|
|
error:
|
2003-01-31 18:57:04 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2002-07-13 04:07:12 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2003-04-09 02:55:18 +00:00
|
|
|
* Common routine for chroot and chdir. Callers must provide a locked vnode
|
|
|
|
* instance.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2003-04-09 02:55:18 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
change_dir(struct vnode *vp, struct thread *td)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2013-09-05 00:19:30 +00:00
|
|
|
#ifdef MAC
|
1994-05-24 10:09:53 +00:00
|
|
|
int error;
|
2013-09-05 00:19:30 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2003-04-09 02:55:18 +00:00
|
|
|
ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked");
|
1994-05-24 10:09:53 +00:00
|
|
|
if (vp->v_type != VDIR)
|
2003-04-09 02:55:18 +00:00
|
|
|
return (ENOTDIR);
|
2002-08-01 03:50:08 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_chdir(td->td_ucred, vp);
|
2013-09-05 09:36:19 +00:00
|
|
|
if (error != 0)
|
2003-04-09 02:55:18 +00:00
|
|
|
return (error);
|
|
|
|
#endif
|
2013-09-05 00:19:30 +00:00
|
|
|
return (VOP_ACCESS(vp, VEXEC, td->td_ucred, td));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
static __inline void
|
|
|
|
flags_to_rights(int flags, cap_rights_t *rightsp)
|
2011-08-13 09:21:16 +00:00
|
|
|
{
|
|
|
|
|
2012-09-25 20:48:49 +00:00
|
|
|
if (flags & O_EXEC) {
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(rightsp, CAP_FEXECVE);
|
2012-09-25 20:48:49 +00:00
|
|
|
} else {
|
|
|
|
switch ((flags & O_ACCMODE)) {
|
|
|
|
case O_RDONLY:
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(rightsp, CAP_READ);
|
2012-09-25 20:48:49 +00:00
|
|
|
break;
|
|
|
|
case O_RDWR:
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(rightsp, CAP_READ);
|
2012-09-25 20:48:49 +00:00
|
|
|
/* FALLTHROUGH */
|
|
|
|
case O_WRONLY:
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(rightsp, CAP_WRITE);
|
2013-03-16 23:19:13 +00:00
|
|
|
if (!(flags & (O_APPEND | O_TRUNC)))
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(rightsp, CAP_SEEK);
|
2012-09-25 20:48:49 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-08-13 09:21:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & O_CREAT)
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(rightsp, CAP_CREATE);
|
2011-08-13 09:21:16 +00:00
|
|
|
|
|
|
|
if (flags & O_TRUNC)
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(rightsp, CAP_FTRUNCATE);
|
2011-08-13 09:21:16 +00:00
|
|
|
|
2013-02-17 11:53:51 +00:00
|
|
|
if (flags & (O_SYNC | O_FSYNC))
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(rightsp, CAP_FSYNC);
|
2013-02-17 11:53:51 +00:00
|
|
|
|
|
|
|
if (flags & (O_EXLOCK | O_SHLOCK))
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_set(rightsp, CAP_FLOCK);
|
2011-08-13 09:21:16 +00:00
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2007-03-05 13:10:58 +00:00
|
|
|
* Check permissions, allocate an open file structure, and call the device
|
|
|
|
* open routine if any.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct open_args {
|
|
|
|
char *path;
|
|
|
|
int flags;
|
|
|
|
int mode;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_open(struct thread *td, struct open_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2002-09-01 20:37:28 +00:00
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_openat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->flags, uap->mode));
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct openat_args {
|
|
|
|
int fd;
|
|
|
|
char *path;
|
|
|
|
int flag;
|
|
|
|
int mode;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_openat(struct thread *td, struct openat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
2016-07-10 09:50:21 +00:00
|
|
|
AUDIT_ARG_FD(uap->fd);
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
return (kern_openat(td, uap->fd, uap->path, UIO_USERSPACE, uap->flag,
|
|
|
|
uap->mode));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_openat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
int flags, int mode)
|
|
|
|
{
|
2001-09-12 08:38:13 +00:00
|
|
|
struct proc *p = td->td_proc;
|
2000-07-04 03:34:11 +00:00
|
|
|
struct filedesc *fdp = p->p_fd;
|
|
|
|
struct file *fp;
|
|
|
|
struct vnode *vp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_t rights;
|
2013-09-05 00:19:30 +00:00
|
|
|
int cmode, error, indx;
|
|
|
|
|
|
|
|
indx = -1;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_FFLAGS(flags);
|
|
|
|
AUDIT_ARG_MODE(mode);
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
cap_rights_init(&rights, CAP_LOOKUP);
|
|
|
|
flags_to_rights(flags, &rights);
|
2008-03-31 11:57:18 +00:00
|
|
|
/*
|
2010-03-11 13:16:06 +00:00
|
|
|
* Only one of the O_EXEC, O_RDONLY, O_WRONLY and O_RDWR flags
|
|
|
|
* may be specified.
|
2008-03-31 11:57:18 +00:00
|
|
|
*/
|
|
|
|
if (flags & O_EXEC) {
|
|
|
|
if (flags & O_ACCMODE)
|
|
|
|
return (EINVAL);
|
2012-06-13 21:11:58 +00:00
|
|
|
} else if ((flags & O_ACCMODE) == O_ACCMODE) {
|
1997-10-22 07:28:51 +00:00
|
|
|
return (EINVAL);
|
2012-06-13 21:13:18 +00:00
|
|
|
} else {
|
2008-03-31 11:57:18 +00:00
|
|
|
flags = FFLAGS(flags);
|
2012-06-13 21:11:58 +00:00
|
|
|
}
|
2008-03-31 11:57:18 +00:00
|
|
|
|
2011-08-11 12:30:23 +00:00
|
|
|
/*
|
2016-02-07 01:04:47 +00:00
|
|
|
* Allocate a file structure. The descriptor to reference it
|
|
|
|
* is allocated and set by finstall() below.
|
2011-08-11 12:30:23 +00:00
|
|
|
*/
|
2012-06-13 21:22:35 +00:00
|
|
|
error = falloc_noinstall(td, &fp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2012-06-13 21:22:35 +00:00
|
|
|
/*
|
|
|
|
* An extra reference on `fp' has been held for us by
|
|
|
|
* falloc_noinstall().
|
|
|
|
*/
|
2007-12-30 01:42:15 +00:00
|
|
|
/* Set the flags early so the finit in devfs can pick them up. */
|
|
|
|
fp->f_flag = flags & FMASK;
|
2013-09-05 00:19:30 +00:00
|
|
|
cmode = ((mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT;
|
2013-01-31 22:20:05 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
&rights, td);
|
2003-08-07 17:08:26 +00:00
|
|
|
td->td_dupfd = -1; /* XXX check for fdopen */
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
error = vn_open(&nd, &flags, cmode, fp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0) {
|
2003-07-27 20:09:13 +00:00
|
|
|
/*
|
|
|
|
* If the vn_open replaced the method vector, something
|
|
|
|
* wonderous happened deep below and we just pass it up
|
|
|
|
* pretending we know what we do.
|
|
|
|
*/
|
2011-08-13 09:21:16 +00:00
|
|
|
if (error == ENXIO && fp->f_ops != &badfileops)
|
|
|
|
goto success;
|
2003-07-27 20:09:13 +00:00
|
|
|
|
2000-11-18 21:01:04 +00:00
|
|
|
/*
|
2012-06-13 21:32:35 +00:00
|
|
|
* Handle special fdopen() case. bleh.
|
2011-08-13 09:21:16 +00:00
|
|
|
*
|
|
|
|
* Don't do this for relative (capability) lookups; we don't
|
|
|
|
* understand exactly what would happen, and we don't think
|
|
|
|
* that it ever should.
|
2000-11-18 21:01:04 +00:00
|
|
|
*/
|
2016-11-02 12:43:15 +00:00
|
|
|
if ((nd.ni_lcf & NI_LCF_STRICTRELATIVE) == 0 &&
|
2011-08-13 09:21:16 +00:00
|
|
|
(error == ENODEV || error == ENXIO) &&
|
2012-06-13 21:11:58 +00:00
|
|
|
td->td_dupfd >= 0) {
|
2012-06-13 21:32:35 +00:00
|
|
|
error = dupfdopen(td, fdp, td->td_dupfd, flags, error,
|
|
|
|
&indx);
|
|
|
|
if (error == 0)
|
2011-08-11 12:30:23 +00:00
|
|
|
goto success;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2012-06-13 21:32:35 +00:00
|
|
|
|
2013-01-31 22:15:41 +00:00
|
|
|
goto bad;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2001-09-12 08:38:13 +00:00
|
|
|
td->td_dupfd = 0;
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1994-05-24 10:09:53 +00:00
|
|
|
vp = nd.ni_vp;
|
1996-12-19 19:42:37 +00:00
|
|
|
|
2010-04-13 08:45:55 +00:00
|
|
|
/*
|
|
|
|
* Store the vnode, for any f_type. Typically, the vnode use
|
|
|
|
* count is decremented by direct call to vn_closefile() for
|
|
|
|
* files that switched type in the cdevsw fdopen() method.
|
|
|
|
*/
|
|
|
|
fp->f_vnode = vp;
|
2007-12-30 01:42:15 +00:00
|
|
|
/*
|
|
|
|
* If the file wasn't claimed by devfs bind it to the normal
|
|
|
|
* vnode operations here.
|
|
|
|
*/
|
|
|
|
if (fp->f_ops == &badfileops) {
|
|
|
|
KASSERT(vp->v_type != VFIFO, ("Unexpected fifo."));
|
|
|
|
fp->f_seqcount = 1;
|
2013-09-05 00:19:30 +00:00
|
|
|
finit(fp, (flags & FMASK) | (fp->f_flag & FHASLOCK),
|
|
|
|
DTYPE_VNODE, vp, &vnops);
|
2007-12-30 01:42:15 +00:00
|
|
|
}
|
2003-06-19 04:10:56 +00:00
|
|
|
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2000-07-04 03:34:11 +00:00
|
|
|
if (flags & O_TRUNC) {
|
2010-04-13 08:52:20 +00:00
|
|
|
error = fo_truncate(fp, 0, td->td_ucred, td);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2000-07-04 03:34:11 +00:00
|
|
|
goto bad;
|
|
|
|
}
|
2011-08-11 12:30:23 +00:00
|
|
|
success:
|
|
|
|
/*
|
|
|
|
* If we haven't already installed the FD (for dupfdopen), do so now.
|
|
|
|
*/
|
2011-08-13 09:21:16 +00:00
|
|
|
if (indx == -1) {
|
Merge Capsicum overhaul:
- Capability is no longer separate descriptor type. Now every descriptor
has set of its own capability rights.
- The cap_new(2) system call is left, but it is no longer documented and
should not be used in new code.
- The new syscall cap_rights_limit(2) should be used instead of
cap_new(2), which limits capability rights of the given descriptor
without creating a new one.
- The cap_getrights(2) syscall is renamed to cap_rights_get(2).
- If CAP_IOCTL capability right is present we can further reduce allowed
ioctls list with the new cap_ioctls_limit(2) syscall. List of allowed
ioctls can be retrived with cap_ioctls_get(2) syscall.
- If CAP_FCNTL capability right is present we can further reduce fcntls
that can be used with the new cap_fcntls_limit(2) syscall and retrive
them with cap_fcntls_get(2).
- To support ioctl and fcntl white-listing the filedesc structure was
heavly modified.
- The audit subsystem, kdump and procstat tools were updated to
recognize new syscalls.
- Capability rights were revised and eventhough I tried hard to provide
backward API and ABI compatibility there are some incompatible changes
that are described in detail below:
CAP_CREATE old behaviour:
- Allow for openat(2)+O_CREAT.
- Allow for linkat(2).
- Allow for symlinkat(2).
CAP_CREATE new behaviour:
- Allow for openat(2)+O_CREAT.
Added CAP_LINKAT:
- Allow for linkat(2). ABI: Reuses CAP_RMDIR bit.
- Allow to be target for renameat(2).
Added CAP_SYMLINKAT:
- Allow for symlinkat(2).
Removed CAP_DELETE. Old behaviour:
- Allow for unlinkat(2) when removing non-directory object.
- Allow to be source for renameat(2).
Removed CAP_RMDIR. Old behaviour:
- Allow for unlinkat(2) when removing directory.
Added CAP_RENAMEAT:
- Required for source directory for the renameat(2) syscall.
Added CAP_UNLINKAT (effectively it replaces CAP_DELETE and CAP_RMDIR):
- Allow for unlinkat(2) on any object.
- Required if target of renameat(2) exists and will be removed by this
call.
Removed CAP_MAPEXEC.
CAP_MMAP old behaviour:
- Allow for mmap(2) with any combination of PROT_NONE, PROT_READ and
PROT_WRITE.
CAP_MMAP new behaviour:
- Allow for mmap(2)+PROT_NONE.
Added CAP_MMAP_R:
- Allow for mmap(PROT_READ).
Added CAP_MMAP_W:
- Allow for mmap(PROT_WRITE).
Added CAP_MMAP_X:
- Allow for mmap(PROT_EXEC).
Added CAP_MMAP_RW:
- Allow for mmap(PROT_READ | PROT_WRITE).
Added CAP_MMAP_RX:
- Allow for mmap(PROT_READ | PROT_EXEC).
Added CAP_MMAP_WX:
- Allow for mmap(PROT_WRITE | PROT_EXEC).
Added CAP_MMAP_RWX:
- Allow for mmap(PROT_READ | PROT_WRITE | PROT_EXEC).
Renamed CAP_MKDIR to CAP_MKDIRAT.
Renamed CAP_MKFIFO to CAP_MKFIFOAT.
Renamed CAP_MKNODE to CAP_MKNODEAT.
CAP_READ old behaviour:
- Allow pread(2).
- Disallow read(2), readv(2) (if there is no CAP_SEEK).
CAP_READ new behaviour:
- Allow read(2), readv(2).
- Disallow pread(2) (CAP_SEEK was also required).
CAP_WRITE old behaviour:
- Allow pwrite(2).
- Disallow write(2), writev(2) (if there is no CAP_SEEK).
CAP_WRITE new behaviour:
- Allow write(2), writev(2).
- Disallow pwrite(2) (CAP_SEEK was also required).
Added convinient defines:
#define CAP_PREAD (CAP_SEEK | CAP_READ)
#define CAP_PWRITE (CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ)
#define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL)
#define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W)
#define CAP_MMAP_RX (CAP_MMAP_R | CAP_MMAP_X)
#define CAP_MMAP_WX (CAP_MMAP_W | CAP_MMAP_X)
#define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
#define CAP_RECV CAP_READ
#define CAP_SEND CAP_WRITE
#define CAP_SOCK_CLIENT \
(CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
#define CAP_SOCK_SERVER \
(CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \
CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \
CAP_SETSOCKOPT | CAP_SHUTDOWN)
Added defines for backward API compatibility:
#define CAP_MAPEXEC CAP_MMAP_X
#define CAP_DELETE CAP_UNLINKAT
#define CAP_MKDIR CAP_MKDIRAT
#define CAP_RMDIR CAP_UNLINKAT
#define CAP_MKFIFO CAP_MKFIFOAT
#define CAP_MKNOD CAP_MKNODAT
#define CAP_SOCK_ALL (CAP_SOCK_CLIENT | CAP_SOCK_SERVER)
Sponsored by: The FreeBSD Foundation
Reviewed by: Christoph Mallon <christoph.mallon@gmx.de>
Many aspects discussed with: rwatson, benl, jonathan
ABI compatibility discussed with: kib
2013-03-02 00:53:12 +00:00
|
|
|
struct filecaps *fcaps;
|
|
|
|
|
2011-08-13 09:21:16 +00:00
|
|
|
#ifdef CAPABILITIES
|
2016-11-02 12:43:15 +00:00
|
|
|
if ((nd.ni_lcf & NI_LCF_STRICTRELATIVE) != 0)
|
Merge Capsicum overhaul:
- Capability is no longer separate descriptor type. Now every descriptor
has set of its own capability rights.
- The cap_new(2) system call is left, but it is no longer documented and
should not be used in new code.
- The new syscall cap_rights_limit(2) should be used instead of
cap_new(2), which limits capability rights of the given descriptor
without creating a new one.
- The cap_getrights(2) syscall is renamed to cap_rights_get(2).
- If CAP_IOCTL capability right is present we can further reduce allowed
ioctls list with the new cap_ioctls_limit(2) syscall. List of allowed
ioctls can be retrived with cap_ioctls_get(2) syscall.
- If CAP_FCNTL capability right is present we can further reduce fcntls
that can be used with the new cap_fcntls_limit(2) syscall and retrive
them with cap_fcntls_get(2).
- To support ioctl and fcntl white-listing the filedesc structure was
heavly modified.
- The audit subsystem, kdump and procstat tools were updated to
recognize new syscalls.
- Capability rights were revised and eventhough I tried hard to provide
backward API and ABI compatibility there are some incompatible changes
that are described in detail below:
CAP_CREATE old behaviour:
- Allow for openat(2)+O_CREAT.
- Allow for linkat(2).
- Allow for symlinkat(2).
CAP_CREATE new behaviour:
- Allow for openat(2)+O_CREAT.
Added CAP_LINKAT:
- Allow for linkat(2). ABI: Reuses CAP_RMDIR bit.
- Allow to be target for renameat(2).
Added CAP_SYMLINKAT:
- Allow for symlinkat(2).
Removed CAP_DELETE. Old behaviour:
- Allow for unlinkat(2) when removing non-directory object.
- Allow to be source for renameat(2).
Removed CAP_RMDIR. Old behaviour:
- Allow for unlinkat(2) when removing directory.
Added CAP_RENAMEAT:
- Required for source directory for the renameat(2) syscall.
Added CAP_UNLINKAT (effectively it replaces CAP_DELETE and CAP_RMDIR):
- Allow for unlinkat(2) on any object.
- Required if target of renameat(2) exists and will be removed by this
call.
Removed CAP_MAPEXEC.
CAP_MMAP old behaviour:
- Allow for mmap(2) with any combination of PROT_NONE, PROT_READ and
PROT_WRITE.
CAP_MMAP new behaviour:
- Allow for mmap(2)+PROT_NONE.
Added CAP_MMAP_R:
- Allow for mmap(PROT_READ).
Added CAP_MMAP_W:
- Allow for mmap(PROT_WRITE).
Added CAP_MMAP_X:
- Allow for mmap(PROT_EXEC).
Added CAP_MMAP_RW:
- Allow for mmap(PROT_READ | PROT_WRITE).
Added CAP_MMAP_RX:
- Allow for mmap(PROT_READ | PROT_EXEC).
Added CAP_MMAP_WX:
- Allow for mmap(PROT_WRITE | PROT_EXEC).
Added CAP_MMAP_RWX:
- Allow for mmap(PROT_READ | PROT_WRITE | PROT_EXEC).
Renamed CAP_MKDIR to CAP_MKDIRAT.
Renamed CAP_MKFIFO to CAP_MKFIFOAT.
Renamed CAP_MKNODE to CAP_MKNODEAT.
CAP_READ old behaviour:
- Allow pread(2).
- Disallow read(2), readv(2) (if there is no CAP_SEEK).
CAP_READ new behaviour:
- Allow read(2), readv(2).
- Disallow pread(2) (CAP_SEEK was also required).
CAP_WRITE old behaviour:
- Allow pwrite(2).
- Disallow write(2), writev(2) (if there is no CAP_SEEK).
CAP_WRITE new behaviour:
- Allow write(2), writev(2).
- Disallow pwrite(2) (CAP_SEEK was also required).
Added convinient defines:
#define CAP_PREAD (CAP_SEEK | CAP_READ)
#define CAP_PWRITE (CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ)
#define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL)
#define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W)
#define CAP_MMAP_RX (CAP_MMAP_R | CAP_MMAP_X)
#define CAP_MMAP_WX (CAP_MMAP_W | CAP_MMAP_X)
#define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
#define CAP_RECV CAP_READ
#define CAP_SEND CAP_WRITE
#define CAP_SOCK_CLIENT \
(CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
#define CAP_SOCK_SERVER \
(CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \
CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \
CAP_SETSOCKOPT | CAP_SHUTDOWN)
Added defines for backward API compatibility:
#define CAP_MAPEXEC CAP_MMAP_X
#define CAP_DELETE CAP_UNLINKAT
#define CAP_MKDIR CAP_MKDIRAT
#define CAP_RMDIR CAP_UNLINKAT
#define CAP_MKFIFO CAP_MKFIFOAT
#define CAP_MKNOD CAP_MKNODAT
#define CAP_SOCK_ALL (CAP_SOCK_CLIENT | CAP_SOCK_SERVER)
Sponsored by: The FreeBSD Foundation
Reviewed by: Christoph Mallon <christoph.mallon@gmx.de>
Many aspects discussed with: rwatson, benl, jonathan
ABI compatibility discussed with: kib
2013-03-02 00:53:12 +00:00
|
|
|
fcaps = &nd.ni_filecaps;
|
|
|
|
else
|
2011-08-13 09:21:16 +00:00
|
|
|
#endif
|
Merge Capsicum overhaul:
- Capability is no longer separate descriptor type. Now every descriptor
has set of its own capability rights.
- The cap_new(2) system call is left, but it is no longer documented and
should not be used in new code.
- The new syscall cap_rights_limit(2) should be used instead of
cap_new(2), which limits capability rights of the given descriptor
without creating a new one.
- The cap_getrights(2) syscall is renamed to cap_rights_get(2).
- If CAP_IOCTL capability right is present we can further reduce allowed
ioctls list with the new cap_ioctls_limit(2) syscall. List of allowed
ioctls can be retrived with cap_ioctls_get(2) syscall.
- If CAP_FCNTL capability right is present we can further reduce fcntls
that can be used with the new cap_fcntls_limit(2) syscall and retrive
them with cap_fcntls_get(2).
- To support ioctl and fcntl white-listing the filedesc structure was
heavly modified.
- The audit subsystem, kdump and procstat tools were updated to
recognize new syscalls.
- Capability rights were revised and eventhough I tried hard to provide
backward API and ABI compatibility there are some incompatible changes
that are described in detail below:
CAP_CREATE old behaviour:
- Allow for openat(2)+O_CREAT.
- Allow for linkat(2).
- Allow for symlinkat(2).
CAP_CREATE new behaviour:
- Allow for openat(2)+O_CREAT.
Added CAP_LINKAT:
- Allow for linkat(2). ABI: Reuses CAP_RMDIR bit.
- Allow to be target for renameat(2).
Added CAP_SYMLINKAT:
- Allow for symlinkat(2).
Removed CAP_DELETE. Old behaviour:
- Allow for unlinkat(2) when removing non-directory object.
- Allow to be source for renameat(2).
Removed CAP_RMDIR. Old behaviour:
- Allow for unlinkat(2) when removing directory.
Added CAP_RENAMEAT:
- Required for source directory for the renameat(2) syscall.
Added CAP_UNLINKAT (effectively it replaces CAP_DELETE and CAP_RMDIR):
- Allow for unlinkat(2) on any object.
- Required if target of renameat(2) exists and will be removed by this
call.
Removed CAP_MAPEXEC.
CAP_MMAP old behaviour:
- Allow for mmap(2) with any combination of PROT_NONE, PROT_READ and
PROT_WRITE.
CAP_MMAP new behaviour:
- Allow for mmap(2)+PROT_NONE.
Added CAP_MMAP_R:
- Allow for mmap(PROT_READ).
Added CAP_MMAP_W:
- Allow for mmap(PROT_WRITE).
Added CAP_MMAP_X:
- Allow for mmap(PROT_EXEC).
Added CAP_MMAP_RW:
- Allow for mmap(PROT_READ | PROT_WRITE).
Added CAP_MMAP_RX:
- Allow for mmap(PROT_READ | PROT_EXEC).
Added CAP_MMAP_WX:
- Allow for mmap(PROT_WRITE | PROT_EXEC).
Added CAP_MMAP_RWX:
- Allow for mmap(PROT_READ | PROT_WRITE | PROT_EXEC).
Renamed CAP_MKDIR to CAP_MKDIRAT.
Renamed CAP_MKFIFO to CAP_MKFIFOAT.
Renamed CAP_MKNODE to CAP_MKNODEAT.
CAP_READ old behaviour:
- Allow pread(2).
- Disallow read(2), readv(2) (if there is no CAP_SEEK).
CAP_READ new behaviour:
- Allow read(2), readv(2).
- Disallow pread(2) (CAP_SEEK was also required).
CAP_WRITE old behaviour:
- Allow pwrite(2).
- Disallow write(2), writev(2) (if there is no CAP_SEEK).
CAP_WRITE new behaviour:
- Allow write(2), writev(2).
- Disallow pwrite(2) (CAP_SEEK was also required).
Added convinient defines:
#define CAP_PREAD (CAP_SEEK | CAP_READ)
#define CAP_PWRITE (CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ)
#define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL)
#define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W)
#define CAP_MMAP_RX (CAP_MMAP_R | CAP_MMAP_X)
#define CAP_MMAP_WX (CAP_MMAP_W | CAP_MMAP_X)
#define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
#define CAP_RECV CAP_READ
#define CAP_SEND CAP_WRITE
#define CAP_SOCK_CLIENT \
(CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
#define CAP_SOCK_SERVER \
(CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \
CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \
CAP_SETSOCKOPT | CAP_SHUTDOWN)
Added defines for backward API compatibility:
#define CAP_MAPEXEC CAP_MMAP_X
#define CAP_DELETE CAP_UNLINKAT
#define CAP_MKDIR CAP_MKDIRAT
#define CAP_RMDIR CAP_UNLINKAT
#define CAP_MKFIFO CAP_MKFIFOAT
#define CAP_MKNOD CAP_MKNODAT
#define CAP_SOCK_ALL (CAP_SOCK_CLIENT | CAP_SOCK_SERVER)
Sponsored by: The FreeBSD Foundation
Reviewed by: Christoph Mallon <christoph.mallon@gmx.de>
Many aspects discussed with: rwatson, benl, jonathan
ABI compatibility discussed with: kib
2013-03-02 00:53:12 +00:00
|
|
|
fcaps = NULL;
|
|
|
|
error = finstall(td, fp, &indx, flags, fcaps);
|
|
|
|
/* On success finstall() consumes fcaps. */
|
|
|
|
if (error != 0) {
|
|
|
|
filecaps_free(&nd.ni_filecaps);
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
filecaps_free(&nd.ni_filecaps);
|
2011-08-13 09:21:16 +00:00
|
|
|
}
|
2011-08-11 12:30:23 +00:00
|
|
|
|
2000-11-18 21:01:04 +00:00
|
|
|
/*
|
|
|
|
* Release our private reference, leaving the one associated with
|
|
|
|
* the descriptor table intact.
|
|
|
|
*/
|
2001-09-12 08:38:13 +00:00
|
|
|
fdrop(fp, td);
|
|
|
|
td->td_retval[0] = indx;
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
2000-07-04 03:34:11 +00:00
|
|
|
bad:
|
2012-06-13 21:38:07 +00:00
|
|
|
KASSERT(indx == -1, ("indx=%d, should be -1", indx));
|
2002-10-07 20:49:22 +00:00
|
|
|
fdrop(fp, td);
|
2000-07-04 03:34:11 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef COMPAT_43
|
|
|
|
/*
|
|
|
|
* Create a file.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct ocreat_args {
|
|
|
|
char *path;
|
|
|
|
int mode;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
ocreat(struct thread *td, struct ocreat_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_openat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
2004-03-16 10:46:42 +00:00
|
|
|
O_WRONLY | O_CREAT | O_TRUNC, uap->mode));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
#endif /* COMPAT_43 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a special file.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
struct mknodat_args {
|
|
|
|
int fd;
|
1994-05-24 10:09:53 +00:00
|
|
|
char *path;
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
mode_t mode;
|
|
|
|
dev_t dev;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
sys_mknodat(struct thread *td, struct mknodat_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode,
|
|
|
|
uap->dev));
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(COMPAT_FREEBSD11)
|
|
|
|
int
|
|
|
|
freebsd11_mknod(struct thread *td,
|
|
|
|
struct freebsd11_mknod_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2002-09-01 20:37:28 +00:00
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_mknodat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->mode, uap->dev));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
int
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd11_mknodat(struct thread *td,
|
|
|
|
struct freebsd11_mknodat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode,
|
|
|
|
uap->dev));
|
|
|
|
}
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
#endif /* COMPAT_FREEBSD11 */
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_mknodat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
int mode, dev_t dev)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct vnode *vp;
|
|
|
|
struct mount *mp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct vattr vattr;
|
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error, whiteout = 0;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_MODE(mode);
|
|
|
|
AUDIT_ARG_DEV(dev);
|
2002-09-01 20:37:28 +00:00
|
|
|
switch (mode & S_IFMT) {
|
This Implements the mumbled about "Jail" feature.
This is a seriously beefed up chroot kind of thing. The process
is jailed along the same lines as a chroot does it, but with
additional tough restrictions imposed on what the superuser can do.
For all I know, it is safe to hand over the root bit inside a
prison to the customer living in that prison, this is what
it was developed for in fact: "real virtual servers".
Each prison has an ip number associated with it, which all IP
communications will be coerced to use and each prison has its own
hostname.
Needless to say, you need more RAM this way, but the advantage is
that each customer can run their own particular version of apache
and not stomp on the toes of their neighbors.
It generally does what one would expect, but setting up a jail
still takes a little knowledge.
A few notes:
I have no scripts for setting up a jail, don't ask me for them.
The IP number should be an alias on one of the interfaces.
mount a /proc in each jail, it will make ps more useable.
/proc/<pid>/status tells the hostname of the prison for
jailed processes.
Quotas are only sensible if you have a mountpoint per prison.
There are no privisions for stopping resource-hogging.
Some "#ifdef INET" and similar may be missing (send patches!)
If somebody wants to take it from here and develop it into
more of a "virtual machine" they should be most welcome!
Tools, comments, patches & documentation most welcome.
Have fun...
Sponsored by: http://www.rndassociates.com/
Run for almost a year by: http://www.servetheweb.com/
1999-04-28 11:38:52 +00:00
|
|
|
case S_IFCHR:
|
|
|
|
case S_IFBLK:
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_VFS_MKNOD_DEV);
|
2016-07-15 09:23:18 +00:00
|
|
|
if (error == 0 && dev == VNOVAL)
|
|
|
|
error = EINVAL;
|
2006-11-06 13:42:10 +00:00
|
|
|
break;
|
|
|
|
case S_IFWHT:
|
|
|
|
error = priv_check(td, PRIV_VFS_MKNOD_WHT);
|
This Implements the mumbled about "Jail" feature.
This is a seriously beefed up chroot kind of thing. The process
is jailed along the same lines as a chroot does it, but with
additional tough restrictions imposed on what the superuser can do.
For all I know, it is safe to hand over the root bit inside a
prison to the customer living in that prison, this is what
it was developed for in fact: "real virtual servers".
Each prison has an ip number associated with it, which all IP
communications will be coerced to use and each prison has its own
hostname.
Needless to say, you need more RAM this way, but the advantage is
that each customer can run their own particular version of apache
and not stomp on the toes of their neighbors.
It generally does what one would expect, but setting up a jail
still takes a little knowledge.
A few notes:
I have no scripts for setting up a jail, don't ask me for them.
The IP number should be an alias on one of the interfaces.
mount a /proc in each jail, it will make ps more useable.
/proc/<pid>/status tells the hostname of the prison for
jailed processes.
Quotas are only sensible if you have a mountpoint per prison.
There are no privisions for stopping resource-hogging.
Some "#ifdef INET" and similar may be missing (send patches!)
If somebody wants to take it from here and develop it into
more of a "virtual machine" they should be most welcome!
Tools, comments, patches & documentation most welcome.
Have fun...
Sponsored by: http://www.rndassociates.com/
Run for almost a year by: http://www.servetheweb.com/
1999-04-28 11:38:52 +00:00
|
|
|
break;
|
2008-06-22 21:51:32 +00:00
|
|
|
case S_IFIFO:
|
|
|
|
if (dev == 0)
|
|
|
|
return (kern_mkfifoat(td, fd, path, pathseg, mode));
|
|
|
|
/* FALLTHROUGH */
|
This Implements the mumbled about "Jail" feature.
This is a seriously beefed up chroot kind of thing. The process
is jailed along the same lines as a chroot does it, but with
additional tough restrictions imposed on what the superuser can do.
For all I know, it is safe to hand over the root bit inside a
prison to the customer living in that prison, this is what
it was developed for in fact: "real virtual servers".
Each prison has an ip number associated with it, which all IP
communications will be coerced to use and each prison has its own
hostname.
Needless to say, you need more RAM this way, but the advantage is
that each customer can run their own particular version of apache
and not stomp on the toes of their neighbors.
It generally does what one would expect, but setting up a jail
still takes a little knowledge.
A few notes:
I have no scripts for setting up a jail, don't ask me for them.
The IP number should be an alias on one of the interfaces.
mount a /proc in each jail, it will make ps more useable.
/proc/<pid>/status tells the hostname of the prison for
jailed processes.
Quotas are only sensible if you have a mountpoint per prison.
There are no privisions for stopping resource-hogging.
Some "#ifdef INET" and similar may be missing (send patches!)
If somebody wants to take it from here and develop it into
more of a "virtual machine" they should be most welcome!
Tools, comments, patches & documentation most welcome.
Have fun...
Sponsored by: http://www.rndassociates.com/
Run for almost a year by: http://www.servetheweb.com/
1999-04-28 11:38:52 +00:00
|
|
|
default:
|
2006-11-06 13:42:10 +00:00
|
|
|
error = EINVAL;
|
This Implements the mumbled about "Jail" feature.
This is a seriously beefed up chroot kind of thing. The process
is jailed along the same lines as a chroot does it, but with
additional tough restrictions imposed on what the superuser can do.
For all I know, it is safe to hand over the root bit inside a
prison to the customer living in that prison, this is what
it was developed for in fact: "real virtual servers".
Each prison has an ip number associated with it, which all IP
communications will be coerced to use and each prison has its own
hostname.
Needless to say, you need more RAM this way, but the advantage is
that each customer can run their own particular version of apache
and not stomp on the toes of their neighbors.
It generally does what one would expect, but setting up a jail
still takes a little knowledge.
A few notes:
I have no scripts for setting up a jail, don't ask me for them.
The IP number should be an alias on one of the interfaces.
mount a /proc in each jail, it will make ps more useable.
/proc/<pid>/status tells the hostname of the prison for
jailed processes.
Quotas are only sensible if you have a mountpoint per prison.
There are no privisions for stopping resource-hogging.
Some "#ifdef INET" and similar may be missing (send patches!)
If somebody wants to take it from here and develop it into
more of a "virtual machine" they should be most welcome!
Tools, comments, patches & documentation most welcome.
Have fun...
Sponsored by: http://www.rndassociates.com/
Run for almost a year by: http://www.servetheweb.com/
1999-04-28 11:38:52 +00:00
|
|
|
break;
|
|
|
|
}
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2000-07-11 22:07:57 +00:00
|
|
|
restart:
|
2000-01-10 00:08:53 +00:00
|
|
|
bwillwrite();
|
2014-12-18 10:01:12 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
|
2018-05-20 05:13:12 +00:00
|
|
|
NOCACHE, pathseg, path, fd, &cap_mknodat_rights,
|
2014-12-18 10:01:12 +00:00
|
|
|
td);
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
vp = nd.ni_vp;
|
2000-07-11 22:07:57 +00:00
|
|
|
if (vp != NULL) {
|
2003-08-05 00:26:51 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
if (vp == nd.ni_dvp)
|
|
|
|
vrele(nd.ni_dvp);
|
|
|
|
else
|
|
|
|
vput(nd.ni_dvp);
|
2006-02-01 00:25:26 +00:00
|
|
|
vrele(vp);
|
2003-08-05 00:26:51 +00:00
|
|
|
return (EEXIST);
|
2000-07-11 22:07:57 +00:00
|
|
|
} else {
|
1994-05-24 10:09:53 +00:00
|
|
|
VATTR_NULL(&vattr);
|
2002-09-01 20:37:28 +00:00
|
|
|
vattr.va_mode = (mode & ALLPERMS) &
|
|
|
|
~td->td_proc->p_fd->fd_cmask;
|
|
|
|
vattr.va_rdev = dev;
|
1997-02-10 02:22:35 +00:00
|
|
|
whiteout = 0;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2002-09-01 20:37:28 +00:00
|
|
|
switch (mode & S_IFMT) {
|
1994-05-24 10:09:53 +00:00
|
|
|
case S_IFCHR:
|
|
|
|
vattr.va_type = VCHR;
|
|
|
|
break;
|
|
|
|
case S_IFBLK:
|
|
|
|
vattr.va_type = VBLK;
|
|
|
|
break;
|
1997-02-10 02:22:35 +00:00
|
|
|
case S_IFWHT:
|
|
|
|
whiteout = 1;
|
|
|
|
break;
|
1994-05-24 10:09:53 +00:00
|
|
|
default:
|
2006-11-06 13:42:10 +00:00
|
|
|
panic("kern_mknod: invalid mode");
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
}
|
2000-07-11 22:07:57 +00:00
|
|
|
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
|
|
|
|
return (error);
|
|
|
|
goto restart;
|
|
|
|
}
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
|
|
|
if (error == 0 && !whiteout)
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp,
|
2002-10-19 20:25:57 +00:00
|
|
|
&nd.ni_cnd, &vattr);
|
|
|
|
#endif
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error == 0) {
|
1999-12-15 23:02:35 +00:00
|
|
|
if (whiteout)
|
1997-02-10 02:22:35 +00:00
|
|
|
error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
|
1999-12-15 23:02:35 +00:00
|
|
|
else {
|
1997-02-10 02:22:35 +00:00
|
|
|
error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
|
|
|
|
&nd.ni_cnd, &vattr);
|
1999-11-13 14:35:50 +00:00
|
|
|
if (error == 0)
|
|
|
|
vput(nd.ni_vp);
|
1997-02-10 02:22:35 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2000-07-11 22:07:57 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
vn_finished_write(mp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-02-10 02:22:35 +00:00
|
|
|
* Create a named pipe.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mkfifo_args {
|
|
|
|
char *path;
|
|
|
|
int mode;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_mkfifo(struct thread *td, struct mkfifo_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_mkfifoat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->mode));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct mkfifoat_args {
|
|
|
|
int fd;
|
|
|
|
char *path;
|
|
|
|
mode_t mode;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_mkfifoat(struct thread *td, struct mkfifoat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_mkfifoat(td, uap->fd, uap->path, UIO_USERSPACE,
|
|
|
|
uap->mode));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_mkfifoat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, int mode)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct vattr vattr;
|
2013-09-05 00:19:30 +00:00
|
|
|
struct nameidata nd;
|
1994-05-24 10:09:53 +00:00
|
|
|
int error;
|
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_MODE(mode);
|
2000-07-11 22:07:57 +00:00
|
|
|
restart:
|
2000-01-10 00:08:53 +00:00
|
|
|
bwillwrite();
|
2014-12-18 10:01:12 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
|
2018-05-20 05:13:12 +00:00
|
|
|
NOCACHE, pathseg, path, fd, &cap_mkfifoat_rights,
|
2014-12-18 10:01:12 +00:00
|
|
|
td);
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
if (nd.ni_vp != NULL) {
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2003-08-05 00:26:51 +00:00
|
|
|
if (nd.ni_vp == nd.ni_dvp)
|
|
|
|
vrele(nd.ni_dvp);
|
|
|
|
else
|
|
|
|
vput(nd.ni_dvp);
|
2006-02-01 00:25:26 +00:00
|
|
|
vrele(nd.ni_vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EEXIST);
|
|
|
|
}
|
2000-07-11 22:07:57 +00:00
|
|
|
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
|
|
|
|
return (error);
|
|
|
|
goto restart;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
VATTR_NULL(&vattr);
|
|
|
|
vattr.va_type = VFIFO;
|
2002-09-01 20:37:28 +00:00
|
|
|
vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask;
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
|
2002-10-19 20:25:57 +00:00
|
|
|
&vattr);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2002-10-19 20:25:57 +00:00
|
|
|
goto out;
|
|
|
|
#endif
|
1998-05-07 04:58:58 +00:00
|
|
|
error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
|
1999-11-13 14:35:50 +00:00
|
|
|
if (error == 0)
|
|
|
|
vput(nd.ni_vp);
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
|
|
|
out:
|
|
|
|
#endif
|
1998-05-07 04:58:58 +00:00
|
|
|
vput(nd.ni_dvp);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
2005-01-24 10:25:44 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1998-05-07 04:58:58 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make a hard file link.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct link_args {
|
|
|
|
char *path;
|
|
|
|
char *link;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_link(struct thread *td, struct link_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_linkat(td, AT_FDCWD, AT_FDCWD, uap->path, uap->link,
|
|
|
|
UIO_USERSPACE, FOLLOW));
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct linkat_args {
|
|
|
|
int fd1;
|
|
|
|
char *path1;
|
|
|
|
int fd2;
|
|
|
|
char *path2;
|
|
|
|
int flag;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_linkat(struct thread *td, struct linkat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
int flag;
|
|
|
|
|
|
|
|
flag = uap->flag;
|
2018-10-25 22:16:34 +00:00
|
|
|
if ((flag & ~(AT_SYMLINK_FOLLOW | AT_BENEATH)) != 0)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
return (kern_linkat(td, uap->fd1, uap->fd2, uap->path1, uap->path2,
|
2018-10-25 22:16:34 +00:00
|
|
|
UIO_USERSPACE, ((flag & AT_SYMLINK_FOLLOW) != 0 ? FOLLOW :
|
|
|
|
NOFOLLOW) | ((flag & AT_BENEATH) != 0 ? BENEATH : 0)));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
2009-06-13 13:09:20 +00:00
|
|
|
int hardlink_check_uid = 0;
|
2004-03-08 20:37:25 +00:00
|
|
|
SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
|
|
|
|
&hardlink_check_uid, 0,
|
|
|
|
"Unprivileged processes cannot create hard links to files owned by other "
|
|
|
|
"users");
|
|
|
|
static int hardlink_check_gid = 0;
|
|
|
|
SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
|
|
|
|
&hardlink_check_gid, 0,
|
|
|
|
"Unprivileged processes cannot create hard links to files owned by other "
|
|
|
|
"groups");
|
|
|
|
|
|
|
|
static int
|
2008-08-28 15:23:18 +00:00
|
|
|
can_hardlink(struct vnode *vp, struct ucred *cred)
|
2004-03-08 20:37:25 +00:00
|
|
|
{
|
|
|
|
struct vattr va;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (!hardlink_check_uid && !hardlink_check_gid)
|
|
|
|
return (0);
|
|
|
|
|
2008-08-28 15:23:18 +00:00
|
|
|
error = VOP_GETATTR(vp, &va, cred);
|
2004-03-08 20:37:25 +00:00
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
|
2006-11-06 13:42:10 +00:00
|
|
|
if (hardlink_check_uid && cred->cr_uid != va.va_uid) {
|
2018-12-11 19:32:16 +00:00
|
|
|
error = priv_check_cred(cred, PRIV_VFS_LINK);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2006-11-06 13:42:10 +00:00
|
|
|
return (error);
|
2004-03-08 20:37:25 +00:00
|
|
|
}
|
|
|
|
|
2006-11-06 13:42:10 +00:00
|
|
|
if (hardlink_check_gid && !groupmember(va.va_gid, cred)) {
|
2018-12-11 19:32:16 +00:00
|
|
|
error = priv_check_cred(cred, PRIV_VFS_LINK);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2006-11-06 13:42:10 +00:00
|
|
|
return (error);
|
2004-03-08 20:37:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_linkat(struct thread *td, int fd1, int fd2, const char *path1,
|
2018-12-07 15:17:29 +00:00
|
|
|
const char *path2, enum uio_seg segflag, int follow)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct nameidata nd;
|
|
|
|
int error;
|
|
|
|
|
2018-12-07 15:17:29 +00:00
|
|
|
do {
|
|
|
|
bwillwrite();
|
2018-12-07 23:05:12 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, segflag,
|
|
|
|
path1, fd1, &cap_linkat_source_rights, td);
|
2018-12-07 15:17:29 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
|
|
|
return (error);
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2018-12-07 23:05:12 +00:00
|
|
|
error = kern_linkat_vp(td, nd.ni_vp, fd2, path2, segflag);
|
|
|
|
} while (error == EAGAIN);
|
2018-12-07 15:17:29 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
kern_linkat_vp(struct thread *td, struct vnode *vp, int fd, const char *path,
|
|
|
|
enum uio_seg segflag)
|
|
|
|
{
|
|
|
|
struct nameidata nd;
|
|
|
|
struct mount *mp;
|
|
|
|
int error;
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
|
2000-07-11 22:07:57 +00:00
|
|
|
if (vp->v_type == VDIR) {
|
|
|
|
vrele(vp);
|
|
|
|
return (EPERM); /* POSIX */
|
|
|
|
}
|
2015-08-27 15:16:41 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, CREATE,
|
2018-12-07 15:17:29 +00:00
|
|
|
LOCKPARENT | SAVENAME | AUDITVNODE2 | NOCACHE, segflag, path, fd,
|
2018-05-20 05:13:12 +00:00
|
|
|
&cap_linkat_target_rights, td);
|
2000-07-11 22:07:57 +00:00
|
|
|
if ((error = namei(&nd)) == 0) {
|
|
|
|
if (nd.ni_vp != NULL) {
|
2014-09-25 20:42:25 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2003-08-05 00:26:51 +00:00
|
|
|
if (nd.ni_dvp == nd.ni_vp)
|
|
|
|
vrele(nd.ni_dvp);
|
|
|
|
else
|
|
|
|
vput(nd.ni_dvp);
|
2006-02-01 00:25:26 +00:00
|
|
|
vrele(nd.ni_vp);
|
2014-09-25 20:42:25 +00:00
|
|
|
vrele(vp);
|
|
|
|
return (EEXIST);
|
|
|
|
} else if (nd.ni_dvp->v_mount != vp->v_mount) {
|
2014-07-16 14:04:46 +00:00
|
|
|
/*
|
2014-09-25 20:42:25 +00:00
|
|
|
* Cross-device link. No need to recheck
|
|
|
|
* vp->v_type, since it cannot change, except
|
|
|
|
* to VBAD.
|
2014-07-16 14:04:46 +00:00
|
|
|
*/
|
2014-09-25 20:42:25 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
vrele(vp);
|
|
|
|
return (EXDEV);
|
|
|
|
} else if ((error = vn_lock(vp, LK_EXCLUSIVE)) == 0) {
|
|
|
|
error = can_hardlink(vp, td->td_ucred);
|
2002-10-05 18:11:36 +00:00
|
|
|
#ifdef MAC
|
2014-09-25 20:42:25 +00:00
|
|
|
if (error == 0)
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_link(td->td_ucred,
|
2004-03-08 20:37:25 +00:00
|
|
|
nd.ni_dvp, vp, &nd.ni_cnd);
|
2002-10-05 18:11:36 +00:00
|
|
|
#endif
|
2014-09-25 20:42:25 +00:00
|
|
|
if (error != 0) {
|
|
|
|
vput(vp);
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
error = vn_start_write(vp, &mp, V_NOWAIT);
|
|
|
|
if (error != 0) {
|
|
|
|
vput(vp);
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
error = vn_start_write(NULL, &mp,
|
|
|
|
V_XSLEEP | PCATCH);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2018-12-07 15:17:29 +00:00
|
|
|
return (EAGAIN);
|
2014-09-25 20:42:25 +00:00
|
|
|
}
|
|
|
|
error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2003-08-05 00:26:51 +00:00
|
|
|
vput(nd.ni_dvp);
|
2014-09-25 20:42:25 +00:00
|
|
|
vn_finished_write(mp);
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2014-07-14 08:41:13 +00:00
|
|
|
} else {
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
vrele(vp);
|
2018-12-07 15:17:29 +00:00
|
|
|
return (EAGAIN);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
vrele(vp);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make a symbolic link.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct symlink_args {
|
|
|
|
char *path;
|
|
|
|
char *link;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_symlink(struct thread *td, struct symlink_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_symlinkat(td, uap->path, AT_FDCWD, uap->link,
|
|
|
|
UIO_USERSPACE));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct symlinkat_args {
|
|
|
|
char *path;
|
|
|
|
int fd;
|
|
|
|
char *path2;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_symlinkat(struct thread *td, struct symlinkat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_symlinkat(td, uap->path1, uap->fd, uap->path2,
|
|
|
|
UIO_USERSPACE));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_symlinkat(struct thread *td, const char *path1, int fd, const char *path2,
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
enum uio_seg segflg)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct vattr vattr;
|
2018-11-02 20:50:22 +00:00
|
|
|
const char *syspath;
|
|
|
|
char *tmppath;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2002-09-01 20:37:28 +00:00
|
|
|
if (segflg == UIO_SYSSPACE) {
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
syspath = path1;
|
2002-09-01 20:37:28 +00:00
|
|
|
} else {
|
2018-11-02 20:50:22 +00:00
|
|
|
tmppath = uma_zalloc(namei_zone, M_WAITOK);
|
|
|
|
if ((error = copyinstr(path1, tmppath, MAXPATHLEN, NULL)) != 0)
|
2002-09-01 20:37:28 +00:00
|
|
|
goto out;
|
2018-11-02 20:50:22 +00:00
|
|
|
syspath = tmppath;
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_TEXT(syspath);
|
2000-07-11 22:07:57 +00:00
|
|
|
restart:
|
2000-01-10 00:08:53 +00:00
|
|
|
bwillwrite();
|
2014-12-18 10:01:12 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
|
2018-05-20 05:13:12 +00:00
|
|
|
NOCACHE, segflg, path2, fd, &cap_symlinkat_rights,
|
2014-12-18 10:01:12 +00:00
|
|
|
td);
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
goto out;
|
|
|
|
if (nd.ni_vp) {
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2003-08-05 00:26:51 +00:00
|
|
|
if (nd.ni_vp == nd.ni_dvp)
|
|
|
|
vrele(nd.ni_dvp);
|
|
|
|
else
|
|
|
|
vput(nd.ni_dvp);
|
2006-02-01 00:25:26 +00:00
|
|
|
vrele(nd.ni_vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
error = EEXIST;
|
|
|
|
goto out;
|
|
|
|
}
|
2000-07-11 22:07:57 +00:00
|
|
|
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
|
2004-05-11 10:42:02 +00:00
|
|
|
goto out;
|
2000-07-11 22:07:57 +00:00
|
|
|
goto restart;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
VATTR_NULL(&vattr);
|
2001-09-12 08:38:13 +00:00
|
|
|
vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
|
|
|
vattr.va_type = VLNK;
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
|
2002-10-19 20:25:57 +00:00
|
|
|
&vattr);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2002-10-19 20:25:57 +00:00
|
|
|
goto out2;
|
|
|
|
#endif
|
2002-09-01 20:37:28 +00:00
|
|
|
error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
|
1999-11-13 20:58:17 +00:00
|
|
|
if (error == 0)
|
|
|
|
vput(nd.ni_vp);
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
|
|
|
out2:
|
|
|
|
#endif
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1998-05-07 04:58:58 +00:00
|
|
|
vput(nd.ni_dvp);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
1994-05-24 10:09:53 +00:00
|
|
|
out:
|
2002-09-01 20:37:28 +00:00
|
|
|
if (segflg != UIO_SYSSPACE)
|
2018-11-02 20:50:22 +00:00
|
|
|
uma_zfree(namei_zone, tmppath);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1997-02-10 02:22:35 +00:00
|
|
|
/*
|
|
|
|
* Delete a whiteout from the filesystem.
|
|
|
|
*/
|
2017-05-17 00:34:34 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct undelete_args {
|
|
|
|
char *path;
|
|
|
|
};
|
|
|
|
#endif
|
1997-02-10 02:22:35 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_undelete(struct thread *td, struct undelete_args *uap)
|
1997-02-10 02:22:35 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
1997-02-10 02:22:35 +00:00
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2000-07-11 22:07:57 +00:00
|
|
|
restart:
|
2000-01-10 00:08:53 +00:00
|
|
|
bwillwrite();
|
2012-10-22 17:50:54 +00:00
|
|
|
NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | AUDITVNODE1,
|
Add pathname and/or vnode argument auditing for the following system calls:
quotactl, statfs, fstatfs, fchdir, chdir, chroot, open, mknod, mkfifo,
link, symlink, undelete, unlink, access, eaccess, stat, lstat, pathconf,
readlink, chflags, lchflags, fchflags, chmod, lchmod, fchmod, chown,
lchown, fchown, utimes, lutimes, futimes, truncate, ftruncate, fsync,
rename, mkdir, rmdir, getdirentries, revoke, lgetfh, getfh, extattrctl,
extattr_set_file, extattr_set_link, extattr_get_file, extattr_get_link,
extattr_delete_file, extattr_delete_link, extattr_list_file, extattr_list_link.
In many cases the pathname and vnode auditing is done within namei lookup
instead of directly in the system call.
Audit the remaining arguments to these system calls:
fstatfs, fchdir, open, mknod, chflags, lchflags, fchflags, chmod, lchmod,
fchmod, chown, lchown, fchown, futimes, ftruncate, fsync, mkdir,
getdirentries.
2006-02-22 16:04:20 +00:00
|
|
|
UIO_USERSPACE, uap->path, td);
|
1997-02-10 02:22:35 +00:00
|
|
|
error = namei(&nd);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1997-02-10 02:22:35 +00:00
|
|
|
return (error);
|
|
|
|
|
|
|
|
if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2003-08-05 00:26:51 +00:00
|
|
|
if (nd.ni_vp == nd.ni_dvp)
|
|
|
|
vrele(nd.ni_dvp);
|
|
|
|
else
|
|
|
|
vput(nd.ni_dvp);
|
2006-02-01 00:25:26 +00:00
|
|
|
if (nd.ni_vp)
|
|
|
|
vrele(nd.ni_vp);
|
1997-02-10 02:22:35 +00:00
|
|
|
return (EEXIST);
|
|
|
|
}
|
2000-07-11 22:07:57 +00:00
|
|
|
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
|
|
|
|
return (error);
|
|
|
|
goto restart;
|
|
|
|
}
|
1999-12-15 23:02:35 +00:00
|
|
|
error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1997-02-10 02:22:35 +00:00
|
|
|
vput(nd.ni_dvp);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
1997-02-10 02:22:35 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Delete a name from the filesystem.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct unlink_args {
|
|
|
|
char *path;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_unlink(struct thread *td, struct unlink_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
|
2019-04-06 09:34:26 +00:00
|
|
|
return (kern_funlinkat(td, AT_FDCWD, uap->path, FD_NONE, UIO_USERSPACE,
|
|
|
|
0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
kern_funlinkat_ex(struct thread *td, int dfd, const char *path, int fd,
|
|
|
|
int flag, enum uio_seg pathseg, ino_t oldinum)
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((flag & ~AT_REMOVEDIR) != 0)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
if ((flag & AT_REMOVEDIR) != 0)
|
|
|
|
return (kern_frmdirat(td, dfd, path, fd, UIO_USERSPACE, 0));
|
|
|
|
|
|
|
|
return (kern_funlinkat(td, dfd, path, fd, UIO_USERSPACE, 0, 0));
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct unlinkat_args {
|
|
|
|
int fd;
|
|
|
|
char *path;
|
|
|
|
int flag;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_unlinkat(struct thread *td, struct unlinkat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
2018-10-25 22:16:34 +00:00
|
|
|
|
2019-04-06 09:34:26 +00:00
|
|
|
return (kern_funlinkat_ex(td, uap->fd, uap->path, FD_NONE, uap->flag,
|
|
|
|
UIO_USERSPACE, 0));
|
|
|
|
}
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
|
2019-04-06 09:34:26 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct funlinkat_args {
|
|
|
|
int dfd;
|
|
|
|
const char *path;
|
|
|
|
int fd;
|
|
|
|
int flag;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
|
|
|
sys_funlinkat(struct thread *td, struct funlinkat_args *uap)
|
|
|
|
{
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
|
2019-04-06 09:34:26 +00:00
|
|
|
return (kern_funlinkat_ex(td, uap->dfd, uap->path, uap->fd, uap->flag,
|
|
|
|
UIO_USERSPACE, 0));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
int
|
2019-04-06 09:34:26 +00:00
|
|
|
kern_funlinkat(struct thread *td, int dfd, const char *path, int fd,
|
2018-11-02 20:50:22 +00:00
|
|
|
enum uio_seg pathseg, int flag, ino_t oldinum)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
2019-04-06 09:34:26 +00:00
|
|
|
struct file *fp;
|
2000-07-11 22:07:57 +00:00
|
|
|
struct vnode *vp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
2010-01-11 20:44:05 +00:00
|
|
|
struct stat sb;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2019-04-06 09:34:26 +00:00
|
|
|
fp = NULL;
|
|
|
|
if (fd != FD_NONE) {
|
2019-04-08 14:23:52 +00:00
|
|
|
error = getvnode(td, fd, &cap_no_rights, &fp);
|
2019-04-06 09:34:26 +00:00
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2000-07-11 22:07:57 +00:00
|
|
|
restart:
|
2000-01-10 00:08:53 +00:00
|
|
|
bwillwrite();
|
2018-10-25 22:16:34 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 |
|
|
|
|
((flag & AT_BENEATH) != 0 ? BENEATH : 0),
|
2019-04-06 09:34:26 +00:00
|
|
|
pathseg, path, dfd, &cap_unlinkat_rights, td);
|
|
|
|
if ((error = namei(&nd)) != 0) {
|
|
|
|
if (error == EINVAL)
|
|
|
|
error = EPERM;
|
|
|
|
goto fdout;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
vp = nd.ni_vp;
|
2010-01-11 20:44:05 +00:00
|
|
|
if (vp->v_type == VDIR && oldinum == 0) {
|
1996-05-24 16:19:23 +00:00
|
|
|
error = EPERM; /* POSIX */
|
2010-01-11 20:44:05 +00:00
|
|
|
} else if (oldinum != 0 &&
|
|
|
|
((error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td)) == 0) &&
|
|
|
|
sb.st_ino != oldinum) {
|
2019-04-06 09:34:26 +00:00
|
|
|
error = EIDRM; /* Identifier removed */
|
|
|
|
} else if (fp != NULL && fp->f_vnode != vp) {
|
|
|
|
if ((fp->f_vnode->v_iflag & VI_DOOMED) != 0)
|
|
|
|
error = EBADF;
|
|
|
|
else
|
|
|
|
error = EDEADLK;
|
2010-01-11 20:44:05 +00:00
|
|
|
} else {
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* The root of a mounted filesystem cannot be deleted.
|
1996-05-24 16:19:23 +00:00
|
|
|
*
|
|
|
|
* XXX: can this only be a VDIR case?
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2002-08-04 10:29:36 +00:00
|
|
|
if (vp->v_vflag & VV_ROOT)
|
1994-05-24 10:09:53 +00:00
|
|
|
error = EBUSY;
|
|
|
|
}
|
2002-08-21 03:55:35 +00:00
|
|
|
if (error == 0) {
|
|
|
|
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2006-02-01 00:25:26 +00:00
|
|
|
vput(nd.ni_dvp);
|
2002-08-21 03:55:35 +00:00
|
|
|
if (vp == nd.ni_dvp)
|
|
|
|
vrele(vp);
|
|
|
|
else
|
|
|
|
vput(vp);
|
|
|
|
if ((error = vn_start_write(NULL, &mp,
|
2019-04-06 09:34:26 +00:00
|
|
|
V_XSLEEP | PCATCH)) != 0) {
|
|
|
|
goto fdout;
|
|
|
|
}
|
2002-08-21 03:55:35 +00:00
|
|
|
goto restart;
|
|
|
|
}
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_unlink(td->td_ucred, nd.ni_dvp, vp,
|
2002-10-19 20:25:57 +00:00
|
|
|
&nd.ni_cnd);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2002-10-19 20:25:57 +00:00
|
|
|
goto out;
|
|
|
|
#endif
|
2013-05-11 11:17:44 +00:00
|
|
|
vfs_notify_upper(vp, VFS_NOTIFY_UPPER_UNLINK);
|
Make our v_usecount vnode reference count work identically to the
original BSD code. The association between the vnode and the vm_object
no longer includes reference counts. The major difference is that
vm_object's are no longer freed gratuitiously from the vnode, and so
once an object is created for the vnode, it will last as long as the
vnode does.
When a vnode object reference count is incremented, then the underlying
vnode reference count is incremented also. The two "objects" are now
more intimately related, and so the interactions are now much less
complex.
When vnodes are now normally placed onto the free queue with an object still
attached. The rundown of the object happens at vnode rundown time, and
happens with exactly the same filesystem semantics of the original VFS
code. There is absolutely no need for vnode_pager_uncache and other
travesties like that anymore.
A side-effect of these changes is that SMP locking should be much simpler,
the I/O copyin/copyout optimizations work, NFS should be more ponderable,
and further work on layered filesystems should be less frustrating, because
of the totally coherent management of the vnode objects and vnodes.
Please be careful with your system while running this code, but I would
greatly appreciate feedback as soon a reasonably possible.
1998-01-06 05:26:17 +00:00
|
|
|
error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
|
|
|
out:
|
|
|
|
#endif
|
2002-08-21 03:55:35 +00:00
|
|
|
vn_finished_write(mp);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2006-02-01 00:25:26 +00:00
|
|
|
vput(nd.ni_dvp);
|
2002-08-21 03:55:35 +00:00
|
|
|
if (vp == nd.ni_dvp)
|
|
|
|
vrele(vp);
|
|
|
|
else
|
|
|
|
vput(vp);
|
2019-04-06 09:34:26 +00:00
|
|
|
fdout:
|
|
|
|
if (fp != NULL)
|
|
|
|
fdrop(fp, td);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reposition read/write file offset.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct lseek_args {
|
|
|
|
int fd;
|
|
|
|
int pad;
|
|
|
|
off_t offset;
|
|
|
|
int whence;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-01-30 12:24:47 +00:00
|
|
|
sys_lseek(struct thread *td, struct lseek_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_lseek(td, uap->fd, uap->offset, uap->whence));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_lseek(struct thread *td, int fd, off_t offset, int whence)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2002-01-14 00:13:45 +00:00
|
|
|
struct file *fp;
|
2013-08-21 17:36:01 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2017-01-30 12:24:47 +00:00
|
|
|
AUDIT_ARG_FD(fd);
|
2018-05-20 05:13:12 +00:00
|
|
|
error = fget(td, fd, &cap_seek_rights, &fp);
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
if (error != 0)
|
2002-01-14 00:13:45 +00:00
|
|
|
return (error);
|
2013-08-21 17:36:01 +00:00
|
|
|
error = (fp->f_ops->fo_flags & DFLAG_SEEKABLE) != 0 ?
|
2017-01-30 12:24:47 +00:00
|
|
|
fo_seek(fp, offset, whence, td) : ESPIPE;
|
2002-01-13 11:58:06 +00:00
|
|
|
fdrop(fp, td);
|
2005-01-24 10:25:44 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2004-06-11 11:16:26 +00:00
|
|
|
#if defined(COMPAT_43)
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Reposition read/write file offset.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct olseek_args {
|
|
|
|
int fd;
|
|
|
|
long offset;
|
|
|
|
int whence;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-01-30 12:24:47 +00:00
|
|
|
olseek(struct thread *td, struct olseek_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2017-01-30 12:24:47 +00:00
|
|
|
|
|
|
|
return (kern_lseek(td, uap->fd, uap->offset, uap->whence));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
#endif /* COMPAT_43 */
|
|
|
|
|
The lseek(2), mmap(2), truncate(2), ftruncate(2), pread(2), and
pwrite(2) syscalls are wrapped to provide compatibility with pre-7.x
kernels which required padding before the off_t parameter. The
fcntl(2) contains compatibility code to handle kernels before the
struct flock was changed during the 8.x CURRENT development. The
shims were reasonable to allow easier revert to the older kernel at
that time.
Now, two or three major releases later, shims do not serve any
purpose. Such old kernels cannot handle current libc, so revert the
compatibility code.
Make padded syscalls support conditional under the COMPAT6 config
option. For COMPAT32, the syscalls were under COMPAT6 already.
Remove WITHOUT_SYSCALL_COMPAT build option, which only purpose was to
(partially) disable the removed shims.
Reviewed by: jhb, imp (previous versions)
Discussed with: peter
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2015-04-18 21:50:13 +00:00
|
|
|
#if defined(COMPAT_FREEBSD6)
|
2007-07-04 22:57:21 +00:00
|
|
|
/* Version with the 'pad' argument */
|
|
|
|
int
|
2017-01-30 12:24:47 +00:00
|
|
|
freebsd6_lseek(struct thread *td, struct freebsd6_lseek_args *uap)
|
2007-07-04 22:57:21 +00:00
|
|
|
{
|
|
|
|
|
2017-01-30 12:24:47 +00:00
|
|
|
return (kern_lseek(td, uap->fd, uap->offset, uap->whence));
|
2007-07-04 22:57:21 +00:00
|
|
|
}
|
The lseek(2), mmap(2), truncate(2), ftruncate(2), pread(2), and
pwrite(2) syscalls are wrapped to provide compatibility with pre-7.x
kernels which required padding before the off_t parameter. The
fcntl(2) contains compatibility code to handle kernels before the
struct flock was changed during the 8.x CURRENT development. The
shims were reasonable to allow easier revert to the older kernel at
that time.
Now, two or three major releases later, shims do not serve any
purpose. Such old kernels cannot handle current libc, so revert the
compatibility code.
Make padded syscalls support conditional under the COMPAT6 config
option. For COMPAT32, the syscalls were under COMPAT6 already.
Remove WITHOUT_SYSCALL_COMPAT build option, which only purpose was to
(partially) disable the removed shims.
Reviewed by: jhb, imp (previous versions)
Discussed with: peter
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2015-04-18 21:50:13 +00:00
|
|
|
#endif
|
2007-07-04 22:57:21 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2001-09-21 21:33:22 +00:00
|
|
|
* Check access permissions using passed credentials.
|
|
|
|
*/
|
|
|
|
static int
|
2017-05-17 00:34:34 +00:00
|
|
|
vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
|
|
|
|
struct thread *td)
|
2001-09-21 21:33:22 +00:00
|
|
|
{
|
2008-10-28 13:44:11 +00:00
|
|
|
accmode_t accmode;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
2001-09-21 21:33:22 +00:00
|
|
|
|
|
|
|
/* Flags == 0 means only check for existence. */
|
2014-10-22 01:53:00 +00:00
|
|
|
if (user_flags == 0)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
accmode = 0;
|
|
|
|
if (user_flags & R_OK)
|
|
|
|
accmode |= VREAD;
|
|
|
|
if (user_flags & W_OK)
|
|
|
|
accmode |= VWRITE;
|
|
|
|
if (user_flags & X_OK)
|
|
|
|
accmode |= VEXEC;
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#ifdef MAC
|
2014-10-22 01:53:00 +00:00
|
|
|
error = mac_vnode_check_access(cred, vp, accmode);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#endif
|
2014-10-22 01:53:00 +00:00
|
|
|
if ((accmode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
|
|
|
|
error = VOP_ACCESS(vp, accmode, cred, td);
|
2001-09-21 21:33:22 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check access permissions using "real" credentials.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct access_args {
|
|
|
|
char *path;
|
2011-11-19 06:35:15 +00:00
|
|
|
int amode;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_access(struct thread *td, struct access_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_accessat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
0, uap->amode));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct faccessat_args {
|
|
|
|
int dirfd;
|
|
|
|
char *path;
|
2011-11-19 06:35:15 +00:00
|
|
|
int amode;
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
int flag;
|
|
|
|
}
|
|
|
|
#endif
|
2008-10-23 21:50:16 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_faccessat(struct thread *td, struct faccessat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_accessat(td, uap->fd, uap->path, UIO_USERSPACE, uap->flag,
|
2011-11-19 06:35:15 +00:00
|
|
|
uap->amode));
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
}
|
|
|
|
|
2002-09-01 20:37:28 +00:00
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_accessat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, int flag, int amode)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2014-10-22 01:09:07 +00:00
|
|
|
struct ucred *cred, *usecred;
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
struct vnode *vp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
2005-01-24 10:25:44 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2018-10-25 22:16:34 +00:00
|
|
|
if ((flag & ~(AT_EACCESS | AT_BENEATH)) != 0)
|
2014-11-13 18:01:51 +00:00
|
|
|
return (EINVAL);
|
2014-09-16 00:56:47 +00:00
|
|
|
if (amode != F_OK && (amode & ~(R_OK | W_OK | X_OK)) != 0)
|
|
|
|
return (EINVAL);
|
|
|
|
|
2000-09-02 12:31:55 +00:00
|
|
|
/*
|
|
|
|
* Create and modify a temporary credential instead of one that
|
2014-10-22 01:09:07 +00:00
|
|
|
* is potentially shared (if we need one).
|
2000-09-02 12:31:55 +00:00
|
|
|
*/
|
2014-10-22 01:09:07 +00:00
|
|
|
cred = td->td_ucred;
|
|
|
|
if ((flag & AT_EACCESS) == 0 &&
|
|
|
|
((cred->cr_uid != cred->cr_ruid ||
|
|
|
|
cred->cr_rgid != cred->cr_groups[0]))) {
|
|
|
|
usecred = crdup(cred);
|
|
|
|
usecred->cr_uid = cred->cr_ruid;
|
|
|
|
usecred->cr_groups[0] = cred->cr_rgid;
|
|
|
|
td->td_ucred = usecred;
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
} else
|
2014-10-22 01:09:07 +00:00
|
|
|
usecred = cred;
|
2011-11-19 06:35:15 +00:00
|
|
|
AUDIT_ARG_VALUE(amode);
|
2012-10-22 17:50:54 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF |
|
2018-10-25 22:16:34 +00:00
|
|
|
AUDITVNODE1 | ((flag & AT_BENEATH) != 0 ? BENEATH : 0),
|
|
|
|
pathseg, path, fd, &cap_fstat_rights, td);
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
2014-10-22 01:09:07 +00:00
|
|
|
goto out;
|
1994-05-24 10:09:53 +00:00
|
|
|
vp = nd.ni_vp;
|
|
|
|
|
2014-10-22 01:09:07 +00:00
|
|
|
error = vn_access(vp, amode, usecred, td);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1994-05-24 10:09:53 +00:00
|
|
|
vput(vp);
|
2014-10-22 01:09:07 +00:00
|
|
|
out:
|
|
|
|
if (usecred != cred) {
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
td->td_ucred = cred;
|
2014-10-22 01:09:07 +00:00
|
|
|
crfree(usecred);
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2001-09-21 21:33:22 +00:00
|
|
|
/*
|
|
|
|
* Check access permissions using "effective" credentials.
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct eaccess_args {
|
|
|
|
char *path;
|
2011-11-19 06:35:15 +00:00
|
|
|
int amode;
|
2001-09-21 21:33:22 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_eaccess(struct thread *td, struct eaccess_args *uap)
|
2006-02-06 22:00:53 +00:00
|
|
|
{
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_accessat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
AT_EACCESS, uap->amode));
|
2001-09-21 21:33:22 +00:00
|
|
|
}
|
|
|
|
|
2004-06-11 11:16:26 +00:00
|
|
|
#if defined(COMPAT_43)
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Get file status; this version follows links.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct ostat_args {
|
|
|
|
char *path;
|
|
|
|
struct ostat *ub;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
ostat(struct thread *td, struct ostat_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
struct ostat osb;
|
|
|
|
int error;
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
&sb, NULL);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
cvtstat(&sb, &osb);
|
2013-09-05 00:19:30 +00:00
|
|
|
return (copyout(&osb, uap->ub, sizeof (osb)));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get file status; this version does not follow links.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct olstat_args {
|
|
|
|
char *path;
|
|
|
|
struct ostat *ub;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
olstat(struct thread *td, struct olstat_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1997-03-31 12:02:53 +00:00
|
|
|
struct stat sb;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct ostat osb;
|
|
|
|
int error;
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
|
|
|
|
UIO_USERSPACE, &sb, NULL);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1997-03-31 12:02:53 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
cvtstat(&sb, &osb);
|
2013-09-05 00:19:30 +00:00
|
|
|
return (copyout(&osb, uap->ub, sizeof (osb)));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert from an old to a new stat structure.
|
2018-06-13 08:50:43 +00:00
|
|
|
* XXX: many values are blindly truncated.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1994-05-25 09:21:21 +00:00
|
|
|
void
|
2017-05-17 00:34:34 +00:00
|
|
|
cvtstat(struct stat *st, struct ostat *ost)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
|
2016-05-31 16:56:30 +00:00
|
|
|
bzero(ost, sizeof(*ost));
|
1994-05-24 10:09:53 +00:00
|
|
|
ost->st_dev = st->st_dev;
|
|
|
|
ost->st_ino = st->st_ino;
|
|
|
|
ost->st_mode = st->st_mode;
|
|
|
|
ost->st_nlink = st->st_nlink;
|
|
|
|
ost->st_uid = st->st_uid;
|
|
|
|
ost->st_gid = st->st_gid;
|
|
|
|
ost->st_rdev = st->st_rdev;
|
2018-06-13 08:50:43 +00:00
|
|
|
ost->st_size = MIN(st->st_size, INT32_MAX);
|
2010-03-28 13:13:22 +00:00
|
|
|
ost->st_atim = st->st_atim;
|
|
|
|
ost->st_mtim = st->st_mtim;
|
|
|
|
ost->st_ctim = st->st_ctim;
|
1994-05-24 10:09:53 +00:00
|
|
|
ost->st_blksize = st->st_blksize;
|
|
|
|
ost->st_blocks = st->st_blocks;
|
|
|
|
ost->st_flags = st->st_flags;
|
|
|
|
ost->st_gen = st->st_gen;
|
|
|
|
}
|
2004-06-11 11:16:26 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2017-06-30 16:10:21 +00:00
|
|
|
#if defined(COMPAT_43) || defined(COMPAT_FREEBSD11)
|
2017-06-05 11:40:30 +00:00
|
|
|
int ino64_trunc_error;
|
|
|
|
SYSCTL_INT(_vfs, OID_AUTO, ino64_trunc_error, CTLFLAG_RW,
|
|
|
|
&ino64_trunc_error, 0,
|
Fix the encoding of major and minor numbers in 64-bit dev_t by restoring
the old encodings for the lower 16 and 32 bits and only using the
higher 32 bits for unusually large major and minor numbers. This
change breaks compatibility with the previous encoding (which was only
used in -current).
Fix truncation to (essentially) 16-bit dev_t in newnfs v3.
Any encoding of device numbers gives an ABI, so it can't be changed
without translations for compatibility. Extra bits give the much
larger complication that the translations need to compress into fewer
bits. Fortunately, more than 32 bits are rarely needed, so
compression is rarely needed except for 16-bit linux dev_t where it
was always needed but never done.
The previous encoding moved the major number into the top 32 bits.
Almost no translation code handled this, so the major number was blindly
truncated away in most 32-bit encodings. E.g., for ffs, mknod(8) with
major = 1 and minor = 2 gave dev_t = 0x10000002; ffs cannot represent
this and blindly truncated it to 2. But if this mknod was run on any
released version of FreeBSD, it gives dev_t = 0x102. ffs can represent
this, but in the previous encoding it was not decoded, giving major = 0,
minor = 0x102.
The presence of bugs was most obvious for exporting dev_t's from an
old system to -current, since bugs in newnfs augment them. I fixed
oldnfs to support 32-bit dev_t in 1996 (r16634), but this regressed
to 16-bit dev_t in newnfs, first to the old 16-bit encoding and then
further in -current. E.g., old ad0 with major = 234, minor = 0x10002
had the correct (major, minor) number on the wire, but newnfs truncated
this to (234, 2) and then the previous encoding shifted the major
number into oblivion as seen by ffs or old applications.
I first tried to fix this by translating on every ABI/API boundary, but
there are too many boundaries and too many sloppy translations by blind
truncation. So use the old encoding for the low 32 bits so that sloppy
translations work no worse than before provided the high 32 bits are
not set. Add some error checking for when bits are lost. Keep not
doing any error checking for translations for almost everything in
compat/linux.
compat/freebsd32/freebsd32_misc.c:
Optionally check for losing bits after possibly-truncating assignments as
before.
compat/linux/linux_stats.c:
Depend on the representation being compatible with Linux's (or just with
itself for local use) and spell some of the translations as assignments in
a macro that hides the details.
fs/nfsclient/nfs_clcomsubs.c:
Essentially the same fix as in 1996, except there is now no possible
truncation in makedev() itself. Also fix nearby style bugs.
kern/vfs_syscalls.c:
As for freebsd32. Also update the sysctl description to include file
numbers, and change it to describe device ids as device numbers.
sys/types.h:
Use inline functions (wrapped by macros) since the expressions are now
a bit too complicated for plain macros. Describe the encoding and
some of the reasons for it. 16-bit compatibility didn't leave many
reasonable choices for the 32-bit encoding, and 32-bit compatibility
doesn't leave many reasonable choices for the 64-bit encoding. My
choice is to put the 8 new minor bits in the low 8 bits of the top 32
bits. This minimizes discontiguities.
Reviewed by: kib (except for rewrite of the comment in linux_stats.c)
2018-06-13 12:22:00 +00:00
|
|
|
"Error on truncation of device, file or inode number, or link count");
|
|
|
|
|
2017-06-05 11:40:30 +00:00
|
|
|
int
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd11_cvtstat(struct stat *st, struct freebsd11_stat *ost)
|
|
|
|
{
|
|
|
|
|
|
|
|
ost->st_dev = st->st_dev;
|
Fix the encoding of major and minor numbers in 64-bit dev_t by restoring
the old encodings for the lower 16 and 32 bits and only using the
higher 32 bits for unusually large major and minor numbers. This
change breaks compatibility with the previous encoding (which was only
used in -current).
Fix truncation to (essentially) 16-bit dev_t in newnfs v3.
Any encoding of device numbers gives an ABI, so it can't be changed
without translations for compatibility. Extra bits give the much
larger complication that the translations need to compress into fewer
bits. Fortunately, more than 32 bits are rarely needed, so
compression is rarely needed except for 16-bit linux dev_t where it
was always needed but never done.
The previous encoding moved the major number into the top 32 bits.
Almost no translation code handled this, so the major number was blindly
truncated away in most 32-bit encodings. E.g., for ffs, mknod(8) with
major = 1 and minor = 2 gave dev_t = 0x10000002; ffs cannot represent
this and blindly truncated it to 2. But if this mknod was run on any
released version of FreeBSD, it gives dev_t = 0x102. ffs can represent
this, but in the previous encoding it was not decoded, giving major = 0,
minor = 0x102.
The presence of bugs was most obvious for exporting dev_t's from an
old system to -current, since bugs in newnfs augment them. I fixed
oldnfs to support 32-bit dev_t in 1996 (r16634), but this regressed
to 16-bit dev_t in newnfs, first to the old 16-bit encoding and then
further in -current. E.g., old ad0 with major = 234, minor = 0x10002
had the correct (major, minor) number on the wire, but newnfs truncated
this to (234, 2) and then the previous encoding shifted the major
number into oblivion as seen by ffs or old applications.
I first tried to fix this by translating on every ABI/API boundary, but
there are too many boundaries and too many sloppy translations by blind
truncation. So use the old encoding for the low 32 bits so that sloppy
translations work no worse than before provided the high 32 bits are
not set. Add some error checking for when bits are lost. Keep not
doing any error checking for translations for almost everything in
compat/linux.
compat/freebsd32/freebsd32_misc.c:
Optionally check for losing bits after possibly-truncating assignments as
before.
compat/linux/linux_stats.c:
Depend on the representation being compatible with Linux's (or just with
itself for local use) and spell some of the translations as assignments in
a macro that hides the details.
fs/nfsclient/nfs_clcomsubs.c:
Essentially the same fix as in 1996, except there is now no possible
truncation in makedev() itself. Also fix nearby style bugs.
kern/vfs_syscalls.c:
As for freebsd32. Also update the sysctl description to include file
numbers, and change it to describe device ids as device numbers.
sys/types.h:
Use inline functions (wrapped by macros) since the expressions are now
a bit too complicated for plain macros. Describe the encoding and
some of the reasons for it. 16-bit compatibility didn't leave many
reasonable choices for the 32-bit encoding, and 32-bit compatibility
doesn't leave many reasonable choices for the 64-bit encoding. My
choice is to put the 8 new minor bits in the low 8 bits of the top 32
bits. This minimizes discontiguities.
Reviewed by: kib (except for rewrite of the comment in linux_stats.c)
2018-06-13 12:22:00 +00:00
|
|
|
if (ost->st_dev != st->st_dev) {
|
|
|
|
switch (ino64_trunc_error) {
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* Since dev_t is almost raw, don't clamp to the
|
|
|
|
* maximum for case 2, but ignore the error.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
return (EOVERFLOW);
|
|
|
|
}
|
|
|
|
}
|
2017-06-05 11:40:30 +00:00
|
|
|
ost->st_ino = st->st_ino;
|
2017-06-09 11:17:08 +00:00
|
|
|
if (ost->st_ino != st->st_ino) {
|
|
|
|
switch (ino64_trunc_error) {
|
|
|
|
default:
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
return (EOVERFLOW);
|
|
|
|
case 2:
|
|
|
|
ost->st_ino = UINT32_MAX;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
ost->st_mode = st->st_mode;
|
2017-06-05 11:40:30 +00:00
|
|
|
ost->st_nlink = st->st_nlink;
|
2017-06-09 11:17:08 +00:00
|
|
|
if (ost->st_nlink != st->st_nlink) {
|
|
|
|
switch (ino64_trunc_error) {
|
|
|
|
default:
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
return (EOVERFLOW);
|
|
|
|
case 2:
|
|
|
|
ost->st_nlink = UINT16_MAX;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
ost->st_uid = st->st_uid;
|
|
|
|
ost->st_gid = st->st_gid;
|
|
|
|
ost->st_rdev = st->st_rdev;
|
Fix the encoding of major and minor numbers in 64-bit dev_t by restoring
the old encodings for the lower 16 and 32 bits and only using the
higher 32 bits for unusually large major and minor numbers. This
change breaks compatibility with the previous encoding (which was only
used in -current).
Fix truncation to (essentially) 16-bit dev_t in newnfs v3.
Any encoding of device numbers gives an ABI, so it can't be changed
without translations for compatibility. Extra bits give the much
larger complication that the translations need to compress into fewer
bits. Fortunately, more than 32 bits are rarely needed, so
compression is rarely needed except for 16-bit linux dev_t where it
was always needed but never done.
The previous encoding moved the major number into the top 32 bits.
Almost no translation code handled this, so the major number was blindly
truncated away in most 32-bit encodings. E.g., for ffs, mknod(8) with
major = 1 and minor = 2 gave dev_t = 0x10000002; ffs cannot represent
this and blindly truncated it to 2. But if this mknod was run on any
released version of FreeBSD, it gives dev_t = 0x102. ffs can represent
this, but in the previous encoding it was not decoded, giving major = 0,
minor = 0x102.
The presence of bugs was most obvious for exporting dev_t's from an
old system to -current, since bugs in newnfs augment them. I fixed
oldnfs to support 32-bit dev_t in 1996 (r16634), but this regressed
to 16-bit dev_t in newnfs, first to the old 16-bit encoding and then
further in -current. E.g., old ad0 with major = 234, minor = 0x10002
had the correct (major, minor) number on the wire, but newnfs truncated
this to (234, 2) and then the previous encoding shifted the major
number into oblivion as seen by ffs or old applications.
I first tried to fix this by translating on every ABI/API boundary, but
there are too many boundaries and too many sloppy translations by blind
truncation. So use the old encoding for the low 32 bits so that sloppy
translations work no worse than before provided the high 32 bits are
not set. Add some error checking for when bits are lost. Keep not
doing any error checking for translations for almost everything in
compat/linux.
compat/freebsd32/freebsd32_misc.c:
Optionally check for losing bits after possibly-truncating assignments as
before.
compat/linux/linux_stats.c:
Depend on the representation being compatible with Linux's (or just with
itself for local use) and spell some of the translations as assignments in
a macro that hides the details.
fs/nfsclient/nfs_clcomsubs.c:
Essentially the same fix as in 1996, except there is now no possible
truncation in makedev() itself. Also fix nearby style bugs.
kern/vfs_syscalls.c:
As for freebsd32. Also update the sysctl description to include file
numbers, and change it to describe device ids as device numbers.
sys/types.h:
Use inline functions (wrapped by macros) since the expressions are now
a bit too complicated for plain macros. Describe the encoding and
some of the reasons for it. 16-bit compatibility didn't leave many
reasonable choices for the 32-bit encoding, and 32-bit compatibility
doesn't leave many reasonable choices for the 64-bit encoding. My
choice is to put the 8 new minor bits in the low 8 bits of the top 32
bits. This minimizes discontiguities.
Reviewed by: kib (except for rewrite of the comment in linux_stats.c)
2018-06-13 12:22:00 +00:00
|
|
|
if (ost->st_rdev != st->st_rdev) {
|
|
|
|
switch (ino64_trunc_error) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
return (EOVERFLOW);
|
|
|
|
}
|
|
|
|
}
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
ost->st_atim = st->st_atim;
|
|
|
|
ost->st_mtim = st->st_mtim;
|
|
|
|
ost->st_ctim = st->st_ctim;
|
|
|
|
ost->st_size = st->st_size;
|
|
|
|
ost->st_blocks = st->st_blocks;
|
|
|
|
ost->st_blksize = st->st_blksize;
|
|
|
|
ost->st_flags = st->st_flags;
|
|
|
|
ost->st_gen = st->st_gen;
|
|
|
|
ost->st_lspare = 0;
|
|
|
|
ost->st_birthtim = st->st_birthtim;
|
|
|
|
bzero((char *)&ost->st_birthtim + sizeof(ost->st_birthtim),
|
|
|
|
sizeof(*ost) - offsetof(struct freebsd11_stat,
|
|
|
|
st_birthtim) - sizeof(ost->st_birthtim));
|
2017-06-05 11:40:30 +00:00
|
|
|
return (0);
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
}
|
|
|
|
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd11_stat(struct thread *td, struct freebsd11_stat_args* uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct stat sb;
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
struct freebsd11_stat osb;
|
1994-05-24 10:09:53 +00:00
|
|
|
int error;
|
2005-02-07 18:44:55 +00:00
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
&sb, NULL);
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2017-06-05 11:40:30 +00:00
|
|
|
error = freebsd11_cvtstat(&sb, &osb);
|
|
|
|
if (error == 0)
|
|
|
|
error = copyout(&osb, uap->ub, sizeof(osb));
|
2005-02-07 18:44:55 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
int
|
|
|
|
freebsd11_lstat(struct thread *td, struct freebsd11_lstat_args* uap)
|
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
struct freebsd11_stat osb;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
|
|
|
|
UIO_USERSPACE, &sb, NULL);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2017-06-05 11:40:30 +00:00
|
|
|
error = freebsd11_cvtstat(&sb, &osb);
|
|
|
|
if (error == 0)
|
|
|
|
error = copyout(&osb, uap->ub, sizeof(osb));
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd11_fhstat(struct thread *td, struct freebsd11_fhstat_args* uap)
|
|
|
|
{
|
|
|
|
struct fhandle fh;
|
|
|
|
struct stat sb;
|
|
|
|
struct freebsd11_stat osb;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
error = kern_fhstat(td, fh, &sb);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2017-06-05 11:40:30 +00:00
|
|
|
error = freebsd11_cvtstat(&sb, &osb);
|
|
|
|
if (error == 0)
|
|
|
|
error = copyout(&osb, uap->sb, sizeof(osb));
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd11_fstatat(struct thread *td, struct freebsd11_fstatat_args* uap)
|
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
struct freebsd11_stat osb;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = kern_statat(td, uap->flag, uap->fd, uap->path,
|
|
|
|
UIO_USERSPACE, &sb, NULL);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2017-06-05 11:40:30 +00:00
|
|
|
error = freebsd11_cvtstat(&sb, &osb);
|
|
|
|
if (error == 0)
|
|
|
|
error = copyout(&osb, uap->buf, sizeof(osb));
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif /* COMPAT_FREEBSD11 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get file status
|
|
|
|
*/
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct fstatat_args {
|
|
|
|
int fd;
|
|
|
|
char *path;
|
|
|
|
struct stat *buf;
|
|
|
|
int flag;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_fstatat(struct thread *td, struct fstatat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = kern_statat(td, uap->flag, uap->fd, uap->path,
|
2014-11-13 18:01:51 +00:00
|
|
|
UIO_USERSPACE, &sb, NULL);
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
if (error == 0)
|
|
|
|
error = copyout(&sb, uap->buf, sizeof (sb));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_statat(struct thread *td, int flag, int fd, const char *path,
|
Don't make Linux stat() open character devices to resolve its name.
The existing code calls kern_open() to resolve the vnode of a pathname
right after a stat(). This is not correct, because it causes random
character devices to be opened in /dev. This means ls'ing a tape
streamer will cause it to rewind, for example. Changes I have made:
- Add kern_statat_vnhook() to allow binary emulators to `post-process'
struct stat, using the proper vnode.
- Remove unneeded printf's from stat() and statfs().
- Make the Linuxolator use kern_statat_vnhook(), replacing
translate_path_major_minor_at().
- Let translate_fd_major_minor() use vp->v_rdev instead of
vp->v_un.vu_cdev.
Result:
crw-rw-rw- 1 root root 0, 14 Feb 20 13:54 /dev/ptmx
crw--w---- 1 root adm 136, 0 Feb 20 14:03 /dev/pts/0
crw--w---- 1 root adm 136, 1 Feb 20 14:02 /dev/pts/1
crw--w---- 1 ed tty 136, 2 Feb 20 14:03 /dev/pts/2
Before this commit, ptmx also had a major number of 136, because it
silently allocated and deallocated a pseudo-terminal. Device nodes that
cannot be opened now have proper major/minor-numbers.
Reviewed by: kib, netchild, rdivacky (thanks!)
2009-02-20 13:05:29 +00:00
|
|
|
enum uio_seg pathseg, struct stat *sbp,
|
|
|
|
void (*hook)(struct vnode *vp, struct stat *sbp))
|
|
|
|
{
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
2012-10-22 17:50:54 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2018-10-25 22:16:34 +00:00
|
|
|
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2018-10-25 22:16:34 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) != 0 ?
|
|
|
|
NOFOLLOW : FOLLOW) | ((flag & AT_BENEATH) != 0 ? BENEATH : 0) |
|
|
|
|
LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, fd,
|
2018-05-09 18:47:24 +00:00
|
|
|
&cap_fstat_rights, td);
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2018-11-29 09:04:10 +00:00
|
|
|
error = vn_stat(nd.ni_vp, sbp, td->td_ucred, NOCRED, td);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error == 0) {
|
2018-11-29 09:04:10 +00:00
|
|
|
SDT_PROBE2(vfs, , stat, mode, path, sbp->st_mode);
|
|
|
|
if (S_ISREG(sbp->st_mode))
|
2015-09-28 12:14:16 +00:00
|
|
|
SDT_PROBE2(vfs, , stat, reg, path, pathseg);
|
Don't make Linux stat() open character devices to resolve its name.
The existing code calls kern_open() to resolve the vnode of a pathname
right after a stat(). This is not correct, because it causes random
character devices to be opened in /dev. This means ls'ing a tape
streamer will cause it to rewind, for example. Changes I have made:
- Add kern_statat_vnhook() to allow binary emulators to `post-process'
struct stat, using the proper vnode.
- Remove unneeded printf's from stat() and statfs().
- Make the Linuxolator use kern_statat_vnhook(), replacing
translate_path_major_minor_at().
- Let translate_fd_major_minor() use vp->v_rdev instead of
vp->v_un.vu_cdev.
Result:
crw-rw-rw- 1 root root 0, 14 Feb 20 13:54 /dev/ptmx
crw--w---- 1 root adm 136, 0 Feb 20 14:03 /dev/pts/0
crw--w---- 1 root adm 136, 1 Feb 20 14:02 /dev/pts/1
crw--w---- 1 ed tty 136, 2 Feb 20 14:03 /dev/pts/2
Before this commit, ptmx also had a major number of 136, because it
silently allocated and deallocated a pseudo-terminal. Device nodes that
cannot be opened now have proper major/minor-numbers.
Reviewed by: kib, netchild, rdivacky (thanks!)
2009-02-20 13:05:29 +00:00
|
|
|
if (__predict_false(hook != NULL))
|
2018-11-29 09:04:10 +00:00
|
|
|
hook(nd.ni_vp, sbp);
|
2008-11-05 19:40:36 +00:00
|
|
|
}
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1994-05-24 10:09:53 +00:00
|
|
|
vput(nd.ni_vp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
#ifdef __STAT_TIME_T_EXT
|
2018-11-29 09:54:27 +00:00
|
|
|
sbp->st_atim_ext = 0;
|
|
|
|
sbp->st_mtim_ext = 0;
|
|
|
|
sbp->st_ctim_ext = 0;
|
|
|
|
sbp->st_btim_ext = 0;
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
#endif
|
2008-02-23 01:01:49 +00:00
|
|
|
#ifdef KTRACE
|
|
|
|
if (KTRPOINT(td, KTR_STRUCT))
|
2018-11-29 09:04:10 +00:00
|
|
|
ktrstat(sbp);
|
2008-02-23 01:01:49 +00:00
|
|
|
#endif
|
2005-02-07 18:44:55 +00:00
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
#if defined(COMPAT_FREEBSD11)
|
2000-09-14 19:13:59 +00:00
|
|
|
/*
|
2005-02-07 18:44:55 +00:00
|
|
|
* Implementation of the NetBSD [l]stat() functions.
|
2000-09-14 19:13:59 +00:00
|
|
|
*/
|
1998-05-11 03:55:28 +00:00
|
|
|
void
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd11_cvtnstat(struct stat *sb, struct nstat *nsb)
|
1998-05-11 03:55:28 +00:00
|
|
|
{
|
2013-09-05 00:19:30 +00:00
|
|
|
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
bzero(nsb, sizeof(*nsb));
|
1998-05-11 03:55:28 +00:00
|
|
|
nsb->st_dev = sb->st_dev;
|
|
|
|
nsb->st_ino = sb->st_ino;
|
|
|
|
nsb->st_mode = sb->st_mode;
|
|
|
|
nsb->st_nlink = sb->st_nlink;
|
|
|
|
nsb->st_uid = sb->st_uid;
|
|
|
|
nsb->st_gid = sb->st_gid;
|
|
|
|
nsb->st_rdev = sb->st_rdev;
|
2010-03-28 13:13:22 +00:00
|
|
|
nsb->st_atim = sb->st_atim;
|
|
|
|
nsb->st_mtim = sb->st_mtim;
|
|
|
|
nsb->st_ctim = sb->st_ctim;
|
1998-05-11 03:55:28 +00:00
|
|
|
nsb->st_size = sb->st_size;
|
|
|
|
nsb->st_blocks = sb->st_blocks;
|
|
|
|
nsb->st_blksize = sb->st_blksize;
|
|
|
|
nsb->st_flags = sb->st_flags;
|
|
|
|
nsb->st_gen = sb->st_gen;
|
2010-03-28 13:13:22 +00:00
|
|
|
nsb->st_birthtim = sb->st_birthtim;
|
1998-05-11 03:55:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
struct freebsd11_nstat_args {
|
1998-05-11 03:55:28 +00:00
|
|
|
char *path;
|
|
|
|
struct nstat *ub;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd11_nstat(struct thread *td, struct freebsd11_nstat_args *uap)
|
1998-05-11 03:55:28 +00:00
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
struct nstat nsb;
|
|
|
|
int error;
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
&sb, NULL);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1998-05-11 03:55:28 +00:00
|
|
|
return (error);
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd11_cvtnstat(&sb, &nsb);
|
2013-09-05 00:19:30 +00:00
|
|
|
return (copyout(&nsb, uap->ub, sizeof (nsb)));
|
1998-05-11 03:55:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-09-14 19:13:59 +00:00
|
|
|
* NetBSD lstat. Get file status; this version does not follow links.
|
1998-05-11 03:55:28 +00:00
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
struct freebsd11_nlstat_args {
|
1998-05-11 03:55:28 +00:00
|
|
|
char *path;
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
struct nstat *ub;
|
1998-05-11 03:55:28 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd11_nlstat(struct thread *td, struct freebsd11_nlstat_args *uap)
|
1998-05-11 03:55:28 +00:00
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
struct nstat nsb;
|
2005-02-07 18:44:55 +00:00
|
|
|
int error;
|
1998-05-11 03:55:28 +00:00
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
|
|
|
|
UIO_USERSPACE, &sb, NULL);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1998-05-11 03:55:28 +00:00
|
|
|
return (error);
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd11_cvtnstat(&sb, &nsb);
|
2013-09-05 00:19:30 +00:00
|
|
|
return (copyout(&nsb, uap->ub, sizeof (nsb)));
|
1998-05-11 03:55:28 +00:00
|
|
|
}
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
#endif /* COMPAT_FREEBSD11 */
|
1998-05-11 03:55:28 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Get configurable pathname variables.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct pathconf_args {
|
|
|
|
char *path;
|
|
|
|
int name;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_pathconf(struct thread *td, struct pathconf_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2018-01-17 22:36:58 +00:00
|
|
|
long value;
|
|
|
|
int error;
|
2005-02-07 21:46:43 +00:00
|
|
|
|
2018-01-17 22:36:58 +00:00
|
|
|
error = kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name, FOLLOW,
|
|
|
|
&value);
|
|
|
|
if (error == 0)
|
|
|
|
td->td_retval[0] = value;
|
|
|
|
return (error);
|
2009-07-08 15:23:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct lpathconf_args {
|
|
|
|
char *path;
|
|
|
|
int name;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_lpathconf(struct thread *td, struct lpathconf_args *uap)
|
2009-07-08 15:23:18 +00:00
|
|
|
{
|
2018-01-17 22:36:58 +00:00
|
|
|
long value;
|
|
|
|
int error;
|
2009-07-08 15:23:18 +00:00
|
|
|
|
2018-01-17 22:36:58 +00:00
|
|
|
error = kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name,
|
|
|
|
NOFOLLOW, &value);
|
|
|
|
if (error == 0)
|
|
|
|
td->td_retval[0] = value;
|
|
|
|
return (error);
|
2005-02-07 21:46:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_pathconf(struct thread *td, const char *path, enum uio_seg pathseg,
|
|
|
|
int name, u_long flags, long *valuep)
|
2005-02-07 21:46:43 +00:00
|
|
|
{
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
2012-10-22 17:50:54 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2012-10-22 17:50:54 +00:00
|
|
|
NDINIT(&nd, LOOKUP, LOCKSHARED | LOCKLEAF | AUDITVNODE1 | flags,
|
|
|
|
pathseg, path, td);
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2002-10-27 18:07:41 +00:00
|
|
|
|
2018-01-17 22:36:58 +00:00
|
|
|
error = VOP_PATHCONF(nd.ni_vp, name, valuep);
|
1994-05-24 10:09:53 +00:00
|
|
|
vput(nd.ni_vp);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return target name of a symbolic link.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct readlink_args {
|
|
|
|
char *path;
|
|
|
|
char *buf;
|
2008-02-12 20:09:04 +00:00
|
|
|
size_t count;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_readlink(struct thread *td, struct readlink_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2002-09-01 20:37:28 +00:00
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_readlinkat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->buf, UIO_USERSPACE, uap->count));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct readlinkat_args {
|
|
|
|
int fd;
|
|
|
|
char *path;
|
|
|
|
char *buf;
|
|
|
|
size_t bufsize;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_readlinkat(struct thread *td, struct readlinkat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_readlinkat(td, uap->fd, uap->path, UIO_USERSPACE,
|
|
|
|
uap->buf, UIO_USERSPACE, uap->bufsize));
|
|
|
|
}
|
2002-09-01 20:37:28 +00:00
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_readlinkat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, char *buf, enum uio_seg bufseg, size_t count)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
struct vnode *vp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2012-02-21 01:05:12 +00:00
|
|
|
if (count > IOSIZE_MAX)
|
2009-05-11 19:58:03 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2013-01-31 22:20:05 +00:00
|
|
|
NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
|
|
|
|
pathseg, path, fd, td);
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1994-05-24 10:09:53 +00:00
|
|
|
vp = nd.ni_vp;
|
2018-12-07 15:17:29 +00:00
|
|
|
|
|
|
|
error = kern_readlink_vp(vp, buf, bufseg, count, td);
|
|
|
|
vput(vp);
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper function to readlink from a vnode
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
kern_readlink_vp(struct vnode *vp, char *buf, enum uio_seg bufseg, size_t count,
|
|
|
|
struct thread *td)
|
|
|
|
{
|
|
|
|
struct iovec aiov;
|
|
|
|
struct uio auio;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
ASSERT_VOP_LOCKED(vp, "kern_readlink_vp(): vp not locked");
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_readlink(td->td_ucred, vp);
|
2018-12-07 15:17:29 +00:00
|
|
|
if (error != 0)
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
return (error);
|
|
|
|
#endif
|
2017-08-01 03:40:19 +00:00
|
|
|
if (vp->v_type != VLNK && (vp->v_vflag & VV_READLINK) == 0)
|
2018-12-07 23:07:51 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
aiov.iov_base = buf;
|
|
|
|
aiov.iov_len = count;
|
|
|
|
auio.uio_iov = &aiov;
|
|
|
|
auio.uio_iovcnt = 1;
|
|
|
|
auio.uio_offset = 0;
|
|
|
|
auio.uio_rw = UIO_READ;
|
|
|
|
auio.uio_segflg = bufseg;
|
|
|
|
auio.uio_td = td;
|
|
|
|
auio.uio_resid = count;
|
|
|
|
error = VOP_READLINK(vp, &auio, td->td_ucred);
|
|
|
|
td->td_retval[0] = count - auio.uio_resid;
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2000-09-14 19:13:59 +00:00
|
|
|
/*
|
|
|
|
* Common implementation code for chflags() and fchflags().
|
|
|
|
*/
|
1998-05-11 03:55:28 +00:00
|
|
|
static int
|
2017-05-17 00:34:34 +00:00
|
|
|
setfflags(struct thread *td, struct vnode *vp, u_long flags)
|
1998-05-11 03:55:28 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
1998-05-11 03:55:28 +00:00
|
|
|
struct vattr vattr;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1998-05-11 03:55:28 +00:00
|
|
|
|
2012-04-20 10:08:30 +00:00
|
|
|
/* We can't support the value matching VNOVAL. */
|
|
|
|
if (flags == VNOVAL)
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
|
1999-08-02 21:34:46 +00:00
|
|
|
/*
|
1999-08-04 04:52:18 +00:00
|
|
|
* Prevent non-root users from setting flags on devices. When
|
|
|
|
* a device is reused, users can retain ownership of the device
|
|
|
|
* if they are allowed to set flags and programs assume that
|
|
|
|
* chown can't fail when done as root.
|
1999-08-02 21:34:46 +00:00
|
|
|
*/
|
2001-10-01 20:01:07 +00:00
|
|
|
if (vp->v_type == VCHR || vp->v_type == VBLK) {
|
2007-06-12 00:12:01 +00:00
|
|
|
error = priv_check(td, PRIV_VFS_CHFLAGS_DEV);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2001-10-01 20:01:07 +00:00
|
|
|
return (error);
|
|
|
|
}
|
1999-08-03 17:07:04 +00:00
|
|
|
|
2000-07-11 22:07:57 +00:00
|
|
|
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
|
|
|
|
return (error);
|
2003-03-05 23:15:23 +00:00
|
|
|
VATTR_NULL(&vattr);
|
|
|
|
vattr.va_flags = flags;
|
2013-03-01 21:57:02 +00:00
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_setflags(td->td_ucred, vp, vattr.va_flags);
|
2003-03-05 23:15:23 +00:00
|
|
|
if (error == 0)
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#endif
|
2008-08-28 15:23:18 +00:00
|
|
|
error = VOP_SETATTR(vp, &vattr, td->td_ucred);
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
1999-08-04 04:52:18 +00:00
|
|
|
return (error);
|
1998-05-11 03:55:28 +00:00
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Change flags of a file given a path name.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct chflags_args {
|
2013-03-21 22:44:33 +00:00
|
|
|
const char *path;
|
|
|
|
u_long flags;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_chflags(struct thread *td, struct chflags_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_chflagsat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->flags, 0));
|
2013-03-21 22:59:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct chflagsat_args {
|
|
|
|
int fd;
|
|
|
|
const char *path;
|
|
|
|
u_long flags;
|
|
|
|
int atflag;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
int
|
|
|
|
sys_chflagsat(struct thread *td, struct chflagsat_args *uap)
|
|
|
|
{
|
|
|
|
|
2018-10-25 22:16:34 +00:00
|
|
|
if ((uap->atflag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
|
2013-03-21 22:59:01 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2018-10-25 22:16:34 +00:00
|
|
|
return (kern_chflagsat(td, uap->fd, uap->path, UIO_USERSPACE,
|
|
|
|
uap->flags, uap->atflag));
|
2013-03-21 22:59:01 +00:00
|
|
|
}
|
|
|
|
|
2002-05-05 23:47:41 +00:00
|
|
|
/*
|
|
|
|
* Same as chflags() but doesn't follow symlinks.
|
|
|
|
*/
|
2017-05-17 00:34:34 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct lchflags_args {
|
|
|
|
const char *path;
|
|
|
|
u_long flags;
|
|
|
|
};
|
|
|
|
#endif
|
2002-05-05 23:47:41 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_lchflags(struct thread *td, struct lchflags_args *uap)
|
2002-05-05 23:47:41 +00:00
|
|
|
{
|
2013-03-21 22:59:01 +00:00
|
|
|
|
|
|
|
return (kern_chflagsat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->flags, AT_SYMLINK_NOFOLLOW));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
kern_chflagsat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, u_long flags, int atflag)
|
|
|
|
{
|
2002-05-05 23:47:41 +00:00
|
|
|
struct nameidata nd;
|
2013-03-21 22:59:01 +00:00
|
|
|
int error, follow;
|
2002-05-05 23:47:41 +00:00
|
|
|
|
2013-03-21 22:59:01 +00:00
|
|
|
AUDIT_ARG_FFLAGS(flags);
|
|
|
|
follow = (atflag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
|
2018-10-25 22:16:34 +00:00
|
|
|
follow |= (atflag & AT_BENEATH) != 0 ? BENEATH : 0;
|
2013-03-21 22:59:01 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
|
2018-05-20 05:13:12 +00:00
|
|
|
&cap_fchflags_rights, td);
|
2002-05-05 23:47:41 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
|
|
|
return (error);
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2013-03-21 22:59:01 +00:00
|
|
|
error = setfflags(td, nd.ni_vp, flags);
|
2002-05-05 23:47:41 +00:00
|
|
|
vrele(nd.ni_vp);
|
2004-01-11 19:52:10 +00:00
|
|
|
return (error);
|
2002-05-05 23:47:41 +00:00
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Change flags of a file given a file descriptor.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct fchflags_args {
|
|
|
|
int fd;
|
2013-03-21 22:44:33 +00:00
|
|
|
u_long flags;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_fchflags(struct thread *td, struct fchflags_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct file *fp;
|
|
|
|
int error;
|
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_FD(uap->fd);
|
|
|
|
AUDIT_ARG_FFLAGS(uap->flags);
|
2018-05-20 05:13:12 +00:00
|
|
|
error = getvnode(td, uap->fd, &cap_fchflags_rights,
|
2015-06-16 13:09:18 +00:00
|
|
|
&fp);
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
Add pathname and/or vnode argument auditing for the following system calls:
quotactl, statfs, fstatfs, fchdir, chdir, chroot, open, mknod, mkfifo,
link, symlink, undelete, unlink, access, eaccess, stat, lstat, pathconf,
readlink, chflags, lchflags, fchflags, chmod, lchmod, fchmod, chown,
lchown, fchown, utimes, lutimes, futimes, truncate, ftruncate, fsync,
rename, mkdir, rmdir, getdirentries, revoke, lgetfh, getfh, extattrctl,
extattr_set_file, extattr_set_link, extattr_get_file, extattr_get_link,
extattr_delete_file, extattr_delete_link, extattr_list_file, extattr_list_link.
In many cases the pathname and vnode auditing is done within namei lookup
instead of directly in the system call.
Audit the remaining arguments to these system calls:
fstatfs, fchdir, open, mknod, chflags, lchflags, fchflags, chmod, lchmod,
fchmod, chown, lchown, fchown, futimes, ftruncate, fsync, mkdir,
getdirentries.
2006-02-22 16:04:20 +00:00
|
|
|
#ifdef AUDIT
|
2008-11-04 22:31:04 +00:00
|
|
|
vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
|
2009-07-28 21:52:24 +00:00
|
|
|
AUDIT_ARG_VNODE1(fp->f_vnode);
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(fp->f_vnode, 0);
|
Add pathname and/or vnode argument auditing for the following system calls:
quotactl, statfs, fstatfs, fchdir, chdir, chroot, open, mknod, mkfifo,
link, symlink, undelete, unlink, access, eaccess, stat, lstat, pathconf,
readlink, chflags, lchflags, fchflags, chmod, lchmod, fchmod, chown,
lchown, fchown, utimes, lutimes, futimes, truncate, ftruncate, fsync,
rename, mkdir, rmdir, getdirentries, revoke, lgetfh, getfh, extattrctl,
extattr_set_file, extattr_set_link, extattr_get_file, extattr_get_link,
extattr_delete_file, extattr_delete_link, extattr_list_file, extattr_list_link.
In many cases the pathname and vnode auditing is done within namei lookup
instead of directly in the system call.
Audit the remaining arguments to these system calls:
fstatfs, fchdir, open, mknod, chflags, lchflags, fchflags, chmod, lchmod,
fchmod, chown, lchown, fchown, futimes, ftruncate, fsync, mkdir,
getdirentries.
2006-02-22 16:04:20 +00:00
|
|
|
#endif
|
2003-06-22 08:41:43 +00:00
|
|
|
error = setfflags(td, fp->f_vnode, uap->flags);
|
2005-12-20 00:49:59 +00:00
|
|
|
fdrop(fp, td);
|
2002-01-13 11:58:06 +00:00
|
|
|
return (error);
|
1998-05-11 03:55:28 +00:00
|
|
|
}
|
|
|
|
|
2000-09-14 19:13:59 +00:00
|
|
|
/*
|
|
|
|
* Common implementation code for chmod(), lchmod() and fchmod().
|
|
|
|
*/
|
2011-08-16 20:07:47 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
setfmode(struct thread *td, struct ucred *cred, struct vnode *vp, int mode)
|
1998-05-11 03:55:28 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
1998-05-11 03:55:28 +00:00
|
|
|
struct vattr vattr;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1998-05-11 03:55:28 +00:00
|
|
|
|
2000-07-11 22:07:57 +00:00
|
|
|
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
|
|
|
|
return (error);
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
1995-10-22 09:32:48 +00:00
|
|
|
VATTR_NULL(&vattr);
|
1998-05-11 03:55:28 +00:00
|
|
|
vattr.va_mode = mode & ALLPERMS;
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#ifdef MAC
|
2011-08-16 20:07:47 +00:00
|
|
|
error = mac_vnode_check_setmode(cred, vp, vattr.va_mode);
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
if (error == 0)
|
|
|
|
#endif
|
2011-08-16 20:07:47 +00:00
|
|
|
error = VOP_SETATTR(vp, &vattr, cred);
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
2004-01-11 19:52:10 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change mode of a file given path name.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct chmod_args {
|
|
|
|
char *path;
|
|
|
|
int mode;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_chmod(struct thread *td, struct chmod_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_fchmodat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->mode, 0));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct fchmodat_args {
|
|
|
|
int dirfd;
|
|
|
|
char *path;
|
|
|
|
mode_t mode;
|
|
|
|
int flag;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_fchmodat(struct thread *td, struct fchmodat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
2018-10-25 22:16:34 +00:00
|
|
|
if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2018-10-25 22:16:34 +00:00
|
|
|
return (kern_fchmodat(td, uap->fd, uap->path, UIO_USERSPACE,
|
|
|
|
uap->mode, uap->flag));
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
}
|
|
|
|
|
1998-05-11 03:55:28 +00:00
|
|
|
/*
|
|
|
|
* Change mode of a file given path name (don't follow links.)
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct lchmod_args {
|
|
|
|
char *path;
|
|
|
|
int mode;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_lchmod(struct thread *td, struct lchmod_args *uap)
|
1998-05-11 03:55:28 +00:00
|
|
|
{
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
|
|
|
|
return (kern_fchmodat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->mode, AT_SYMLINK_NOFOLLOW));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_fchmodat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, mode_t mode, int flag)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
1998-05-11 03:55:28 +00:00
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error, follow;
|
1998-05-11 03:55:28 +00:00
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_MODE(mode);
|
2018-10-25 22:16:34 +00:00
|
|
|
follow = (flag & AT_SYMLINK_NOFOLLOW) != 0 ? NOFOLLOW : FOLLOW;
|
|
|
|
follow |= (flag & AT_BENEATH) != 0 ? BENEATH : 0;
|
2013-03-16 22:36:24 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
|
2018-05-20 05:13:12 +00:00
|
|
|
&cap_fchmod_rights, td);
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1998-05-11 03:55:28 +00:00
|
|
|
return (error);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2011-08-16 20:07:47 +00:00
|
|
|
error = setfmode(td, td->td_ucred, nd.ni_vp, mode);
|
1998-05-11 03:55:28 +00:00
|
|
|
vrele(nd.ni_vp);
|
2004-01-11 19:52:10 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change mode of a file given a file descriptor.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct fchmod_args {
|
|
|
|
int fd;
|
|
|
|
int mode;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_fchmod(struct thread *td, struct fchmod_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct file *fp;
|
|
|
|
int error;
|
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_FD(uap->fd);
|
|
|
|
AUDIT_ARG_MODE(uap->mode);
|
2011-08-16 20:07:47 +00:00
|
|
|
|
2018-05-20 05:13:12 +00:00
|
|
|
error = fget(td, uap->fd, &cap_fchmod_rights, &fp);
|
2011-08-16 20:07:47 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2011-08-16 20:07:47 +00:00
|
|
|
error = fo_chmod(fp, uap->mode, td->td_ucred, td);
|
2005-12-20 00:49:59 +00:00
|
|
|
fdrop(fp, td);
|
2002-01-13 11:58:06 +00:00
|
|
|
return (error);
|
1998-05-11 03:55:28 +00:00
|
|
|
}
|
|
|
|
|
2000-09-14 19:13:59 +00:00
|
|
|
/*
|
|
|
|
* Common implementation for chown(), lchown(), and fchown()
|
|
|
|
*/
|
2011-08-16 20:07:47 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
setfown(struct thread *td, struct ucred *cred, struct vnode *vp, uid_t uid,
|
|
|
|
gid_t gid)
|
1998-05-11 03:55:28 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
1998-05-11 03:55:28 +00:00
|
|
|
struct vattr vattr;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1998-05-11 03:55:28 +00:00
|
|
|
|
2000-07-11 22:07:57 +00:00
|
|
|
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
|
|
|
|
return (error);
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
1995-10-22 09:32:48 +00:00
|
|
|
VATTR_NULL(&vattr);
|
1998-05-11 03:55:28 +00:00
|
|
|
vattr.va_uid = uid;
|
|
|
|
vattr.va_gid = gid;
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#ifdef MAC
|
2011-08-16 20:07:47 +00:00
|
|
|
error = mac_vnode_check_setowner(cred, vp, vattr.va_uid,
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
vattr.va_gid);
|
|
|
|
if (error == 0)
|
|
|
|
#endif
|
2011-08-16 20:07:47 +00:00
|
|
|
error = VOP_SETATTR(vp, &vattr, cred);
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
2004-01-11 19:52:10 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set ownership given a path name.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct chown_args {
|
|
|
|
char *path;
|
|
|
|
int uid;
|
|
|
|
int gid;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_chown(struct thread *td, struct chown_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2002-09-01 20:37:28 +00:00
|
|
|
|
2014-11-13 23:51:13 +00:00
|
|
|
return (kern_fchownat(td, AT_FDCWD, uap->path, UIO_USERSPACE, uap->uid,
|
2014-11-13 18:01:51 +00:00
|
|
|
uap->gid, 0));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct fchownat_args {
|
|
|
|
int fd;
|
|
|
|
const char * path;
|
|
|
|
uid_t uid;
|
|
|
|
gid_t gid;
|
|
|
|
int flag;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_fchownat(struct thread *td, struct fchownat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
2018-10-25 22:16:34 +00:00
|
|
|
if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
return (kern_fchownat(td, uap->fd, uap->path, UIO_USERSPACE, uap->uid,
|
|
|
|
uap->gid, uap->flag));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_fchownat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, int uid, int gid, int flag)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
2012-10-22 17:50:54 +00:00
|
|
|
int error, follow;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_OWNER(uid, gid);
|
2008-04-07 00:29:32 +00:00
|
|
|
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
|
2018-10-25 22:16:34 +00:00
|
|
|
follow |= (flag & AT_BENEATH) != 0 ? BENEATH : 0;
|
2013-01-31 22:20:05 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
|
2018-05-20 05:13:12 +00:00
|
|
|
&cap_fchown_rights, td);
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2011-08-16 20:07:47 +00:00
|
|
|
error = setfown(td, td->td_ucred, nd.ni_vp, uid, gid);
|
1998-05-11 03:55:28 +00:00
|
|
|
vrele(nd.ni_vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1997-03-31 12:21:37 +00:00
|
|
|
/*
|
|
|
|
* Set ownership given a path name, do not cross symlinks.
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct lchown_args {
|
|
|
|
char *path;
|
|
|
|
int uid;
|
|
|
|
int gid;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_lchown(struct thread *td, struct lchown_args *uap)
|
1997-03-31 12:21:37 +00:00
|
|
|
{
|
2002-09-01 20:37:28 +00:00
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_fchownat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->uid, uap->gid, AT_SYMLINK_NOFOLLOW));
|
1997-03-31 12:21:37 +00:00
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Set ownership given a file descriptor.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct fchown_args {
|
|
|
|
int fd;
|
|
|
|
int uid;
|
|
|
|
int gid;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_fchown(struct thread *td, struct fchown_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct file *fp;
|
|
|
|
int error;
|
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_FD(uap->fd);
|
|
|
|
AUDIT_ARG_OWNER(uap->uid, uap->gid);
|
2018-05-20 05:13:12 +00:00
|
|
|
error = fget(td, uap->fd, &cap_fchown_rights, &fp);
|
2011-08-16 20:07:47 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2011-08-16 20:07:47 +00:00
|
|
|
error = fo_chown(fp, uap->uid, uap->gid, td->td_ucred, td);
|
2005-12-20 00:49:59 +00:00
|
|
|
fdrop(fp, td);
|
2002-01-13 11:58:06 +00:00
|
|
|
return (error);
|
1998-05-11 03:55:28 +00:00
|
|
|
}
|
|
|
|
|
2000-09-14 19:13:59 +00:00
|
|
|
/*
|
|
|
|
* Common implementation code for utimes(), lutimes(), and futimes().
|
|
|
|
*/
|
1998-05-11 03:55:28 +00:00
|
|
|
static int
|
2017-05-17 00:34:34 +00:00
|
|
|
getutimes(const struct timeval *usrtvp, enum uio_seg tvpseg,
|
|
|
|
struct timespec *tsp)
|
1999-08-22 01:46:57 +00:00
|
|
|
{
|
2006-01-04 00:47:13 +00:00
|
|
|
struct timeval tv[2];
|
2002-09-01 20:37:28 +00:00
|
|
|
const struct timeval *tvp;
|
1999-08-22 01:46:57 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
if (usrtvp == NULL) {
|
2009-08-26 14:32:37 +00:00
|
|
|
vfs_timestamp(&tsp[0]);
|
1999-08-22 01:46:57 +00:00
|
|
|
tsp[1] = tsp[0];
|
|
|
|
} else {
|
2002-09-01 20:37:28 +00:00
|
|
|
if (tvpseg == UIO_SYSSPACE) {
|
|
|
|
tvp = usrtvp;
|
|
|
|
} else {
|
|
|
|
if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0)
|
|
|
|
return (error);
|
|
|
|
tvp = tv;
|
|
|
|
}
|
|
|
|
|
2006-01-04 07:50:54 +00:00
|
|
|
if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 ||
|
|
|
|
tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
|
2006-01-04 00:47:13 +00:00
|
|
|
return (EINVAL);
|
|
|
|
TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
|
|
|
|
TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
|
1999-08-22 01:46:57 +00:00
|
|
|
}
|
2004-01-11 19:52:10 +00:00
|
|
|
return (0);
|
1999-08-22 01:46:57 +00:00
|
|
|
}
|
|
|
|
|
2000-09-14 19:13:59 +00:00
|
|
|
/*
|
2015-01-23 21:07:08 +00:00
|
|
|
* Common implementation code for futimens(), utimensat().
|
|
|
|
*/
|
|
|
|
#define UTIMENS_NULL 0x1
|
|
|
|
#define UTIMENS_EXIT 0x2
|
|
|
|
static int
|
|
|
|
getutimens(const struct timespec *usrtsp, enum uio_seg tspseg,
|
|
|
|
struct timespec *tsp, int *retflags)
|
|
|
|
{
|
|
|
|
struct timespec tsnow;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
vfs_timestamp(&tsnow);
|
|
|
|
*retflags = 0;
|
|
|
|
if (usrtsp == NULL) {
|
|
|
|
tsp[0] = tsnow;
|
|
|
|
tsp[1] = tsnow;
|
|
|
|
*retflags |= UTIMENS_NULL;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if (tspseg == UIO_SYSSPACE) {
|
|
|
|
tsp[0] = usrtsp[0];
|
|
|
|
tsp[1] = usrtsp[1];
|
|
|
|
} else if ((error = copyin(usrtsp, tsp, sizeof(*tsp) * 2)) != 0)
|
|
|
|
return (error);
|
|
|
|
if (tsp[0].tv_nsec == UTIME_OMIT && tsp[1].tv_nsec == UTIME_OMIT)
|
|
|
|
*retflags |= UTIMENS_EXIT;
|
|
|
|
if (tsp[0].tv_nsec == UTIME_NOW && tsp[1].tv_nsec == UTIME_NOW)
|
|
|
|
*retflags |= UTIMENS_NULL;
|
|
|
|
if (tsp[0].tv_nsec == UTIME_OMIT)
|
|
|
|
tsp[0].tv_sec = VNOVAL;
|
|
|
|
else if (tsp[0].tv_nsec == UTIME_NOW)
|
|
|
|
tsp[0] = tsnow;
|
|
|
|
else if (tsp[0].tv_nsec < 0 || tsp[0].tv_nsec >= 1000000000L)
|
|
|
|
return (EINVAL);
|
|
|
|
if (tsp[1].tv_nsec == UTIME_OMIT)
|
|
|
|
tsp[1].tv_sec = VNOVAL;
|
|
|
|
else if (tsp[1].tv_nsec == UTIME_NOW)
|
|
|
|
tsp[1] = tsnow;
|
|
|
|
else if (tsp[1].tv_nsec < 0 || tsp[1].tv_nsec >= 1000000000L)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Common implementation code for utimes(), lutimes(), futimes(), futimens(),
|
|
|
|
* and utimensat().
|
2000-09-14 19:13:59 +00:00
|
|
|
*/
|
1999-08-22 01:46:57 +00:00
|
|
|
static int
|
2017-05-17 00:34:34 +00:00
|
|
|
setutimes(struct thread *td, struct vnode *vp, const struct timespec *ts,
|
|
|
|
int numtimes, int nullflag)
|
1998-05-11 03:55:28 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
1998-05-11 03:55:28 +00:00
|
|
|
struct vattr vattr;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error, setbirthtime;
|
1998-05-11 03:55:28 +00:00
|
|
|
|
2000-07-11 22:07:57 +00:00
|
|
|
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
|
|
|
|
return (error);
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
2002-07-17 02:03:19 +00:00
|
|
|
setbirthtime = 0;
|
2008-08-28 15:23:18 +00:00
|
|
|
if (numtimes < 3 && !VOP_GETATTR(vp, &vattr, td->td_ucred) &&
|
2002-07-17 02:03:19 +00:00
|
|
|
timespeccmp(&ts[1], &vattr.va_birthtime, < ))
|
|
|
|
setbirthtime = 1;
|
1995-10-22 09:32:48 +00:00
|
|
|
VATTR_NULL(&vattr);
|
1999-08-22 01:46:57 +00:00
|
|
|
vattr.va_atime = ts[0];
|
|
|
|
vattr.va_mtime = ts[1];
|
2002-07-17 02:03:19 +00:00
|
|
|
if (setbirthtime)
|
|
|
|
vattr.va_birthtime = ts[1];
|
|
|
|
if (numtimes > 2)
|
|
|
|
vattr.va_birthtime = ts[2];
|
1998-05-11 03:55:28 +00:00
|
|
|
if (nullflag)
|
|
|
|
vattr.va_vaflags |= VA_UTIMES_NULL;
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_setutimes(td->td_ucred, vp, vattr.va_atime,
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
vattr.va_mtime);
|
|
|
|
#endif
|
2002-10-02 09:09:25 +00:00
|
|
|
if (error == 0)
|
2008-08-28 15:23:18 +00:00
|
|
|
error = VOP_SETATTR(vp, &vattr, td->td_ucred);
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
2004-01-11 19:52:10 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the access and modification times of a file.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct utimes_args {
|
|
|
|
char *path;
|
|
|
|
struct timeval *tptr;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_utimes(struct thread *td, struct utimes_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2002-09-01 20:37:28 +00:00
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_utimesat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->tptr, UIO_USERSPACE));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct futimesat_args {
|
|
|
|
int fd;
|
|
|
|
const char * path;
|
|
|
|
const struct timeval * times;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_futimesat(struct thread *td, struct futimesat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
|
|
|
|
uap->times, UIO_USERSPACE));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_utimesat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
struct timespec ts[2];
|
2012-10-22 17:50:54 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2002-09-01 20:37:28 +00:00
|
|
|
if ((error = getutimes(tptr, tptrseg, ts)) != 0)
|
1999-08-22 01:46:57 +00:00
|
|
|
return (error);
|
2013-01-31 22:20:05 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
|
2018-05-20 05:13:12 +00:00
|
|
|
&cap_futimes_rights, td);
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2002-09-01 20:37:28 +00:00
|
|
|
error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
|
1998-05-11 03:55:28 +00:00
|
|
|
vrele(nd.ni_vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1998-05-11 03:55:28 +00:00
|
|
|
/*
|
|
|
|
* Set the access and modification times of a file.
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct lutimes_args {
|
|
|
|
char *path;
|
|
|
|
struct timeval *tptr;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_lutimes(struct thread *td, struct lutimes_args *uap)
|
1998-05-11 03:55:28 +00:00
|
|
|
{
|
2002-09-01 20:37:28 +00:00
|
|
|
|
|
|
|
return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr,
|
|
|
|
UIO_USERSPACE));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_lutimes(struct thread *td, const char *path, enum uio_seg pathseg,
|
2002-09-01 20:37:28 +00:00
|
|
|
struct timeval *tptr, enum uio_seg tptrseg)
|
|
|
|
{
|
1999-08-22 01:46:57 +00:00
|
|
|
struct timespec ts[2];
|
1998-05-11 03:55:28 +00:00
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1998-05-11 03:55:28 +00:00
|
|
|
|
2002-09-01 20:37:28 +00:00
|
|
|
if ((error = getutimes(tptr, tptrseg, ts)) != 0)
|
1999-08-22 01:46:57 +00:00
|
|
|
return (error);
|
2012-10-22 17:50:54 +00:00
|
|
|
NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, pathseg, path, td);
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1998-05-11 03:55:28 +00:00
|
|
|
return (error);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2002-09-01 20:37:28 +00:00
|
|
|
error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
|
1998-05-11 03:55:28 +00:00
|
|
|
vrele(nd.ni_vp);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the access and modification times of a file.
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct futimes_args {
|
|
|
|
int fd;
|
|
|
|
struct timeval *tptr;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_futimes(struct thread *td, struct futimes_args *uap)
|
1998-05-11 03:55:28 +00:00
|
|
|
{
|
2002-09-01 20:37:28 +00:00
|
|
|
|
|
|
|
return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_futimes(struct thread *td, int fd, struct timeval *tptr,
|
|
|
|
enum uio_seg tptrseg)
|
|
|
|
{
|
1999-08-22 01:46:57 +00:00
|
|
|
struct timespec ts[2];
|
1998-05-11 03:55:28 +00:00
|
|
|
struct file *fp;
|
|
|
|
int error;
|
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_FD(fd);
|
2013-09-05 00:19:30 +00:00
|
|
|
error = getutimes(tptr, tptrseg, ts);
|
|
|
|
if (error != 0)
|
1999-08-22 01:46:57 +00:00
|
|
|
return (error);
|
2018-05-20 05:13:12 +00:00
|
|
|
error = getvnode(td, fd, &cap_futimes_rights, &fp);
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
if (error != 0)
|
1998-05-11 03:55:28 +00:00
|
|
|
return (error);
|
Add pathname and/or vnode argument auditing for the following system calls:
quotactl, statfs, fstatfs, fchdir, chdir, chroot, open, mknod, mkfifo,
link, symlink, undelete, unlink, access, eaccess, stat, lstat, pathconf,
readlink, chflags, lchflags, fchflags, chmod, lchmod, fchmod, chown,
lchown, fchown, utimes, lutimes, futimes, truncate, ftruncate, fsync,
rename, mkdir, rmdir, getdirentries, revoke, lgetfh, getfh, extattrctl,
extattr_set_file, extattr_set_link, extattr_get_file, extattr_get_link,
extattr_delete_file, extattr_delete_link, extattr_list_file, extattr_list_link.
In many cases the pathname and vnode auditing is done within namei lookup
instead of directly in the system call.
Audit the remaining arguments to these system calls:
fstatfs, fchdir, open, mknod, chflags, lchflags, fchflags, chmod, lchmod,
fchmod, chown, lchown, fchown, futimes, ftruncate, fsync, mkdir,
getdirentries.
2006-02-22 16:04:20 +00:00
|
|
|
#ifdef AUDIT
|
2008-11-04 22:31:04 +00:00
|
|
|
vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
|
2009-07-28 21:52:24 +00:00
|
|
|
AUDIT_ARG_VNODE1(fp->f_vnode);
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(fp->f_vnode, 0);
|
Add pathname and/or vnode argument auditing for the following system calls:
quotactl, statfs, fstatfs, fchdir, chdir, chroot, open, mknod, mkfifo,
link, symlink, undelete, unlink, access, eaccess, stat, lstat, pathconf,
readlink, chflags, lchflags, fchflags, chmod, lchmod, fchmod, chown,
lchown, fchown, utimes, lutimes, futimes, truncate, ftruncate, fsync,
rename, mkdir, rmdir, getdirentries, revoke, lgetfh, getfh, extattrctl,
extattr_set_file, extattr_set_link, extattr_get_file, extattr_get_link,
extattr_delete_file, extattr_delete_link, extattr_list_file, extattr_list_link.
In many cases the pathname and vnode auditing is done within namei lookup
instead of directly in the system call.
Audit the remaining arguments to these system calls:
fstatfs, fchdir, open, mknod, chflags, lchflags, fchflags, chmod, lchmod,
fchmod, chown, lchown, fchown, futimes, ftruncate, fsync, mkdir,
getdirentries.
2006-02-22 16:04:20 +00:00
|
|
|
#endif
|
2003-06-22 08:41:43 +00:00
|
|
|
error = setutimes(td, fp->f_vnode, ts, 2, tptr == NULL);
|
2005-12-20 00:49:59 +00:00
|
|
|
fdrop(fp, td);
|
2002-01-13 11:58:06 +00:00
|
|
|
return (error);
|
1998-05-11 03:55:28 +00:00
|
|
|
}
|
|
|
|
|
2015-01-23 21:07:08 +00:00
|
|
|
int
|
|
|
|
sys_futimens(struct thread *td, struct futimens_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_futimens(td, uap->fd, uap->times, UIO_USERSPACE));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_futimens(struct thread *td, int fd, struct timespec *tptr,
|
|
|
|
enum uio_seg tptrseg)
|
|
|
|
{
|
|
|
|
struct timespec ts[2];
|
|
|
|
struct file *fp;
|
|
|
|
int error, flags;
|
|
|
|
|
|
|
|
AUDIT_ARG_FD(fd);
|
|
|
|
error = getutimens(tptr, tptrseg, ts, &flags);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
if (flags & UTIMENS_EXIT)
|
|
|
|
return (0);
|
2018-05-20 05:13:12 +00:00
|
|
|
error = getvnode(td, fd, &cap_futimes_rights, &fp);
|
2015-01-23 21:07:08 +00:00
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
#ifdef AUDIT
|
|
|
|
vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
|
|
|
|
AUDIT_ARG_VNODE1(fp->f_vnode);
|
|
|
|
VOP_UNLOCK(fp->f_vnode, 0);
|
|
|
|
#endif
|
|
|
|
error = setutimes(td, fp->f_vnode, ts, 2, flags & UTIMENS_NULL);
|
|
|
|
fdrop(fp, td);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
sys_utimensat(struct thread *td, struct utimensat_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_utimensat(td, uap->fd, uap->path, UIO_USERSPACE,
|
|
|
|
uap->times, UIO_USERSPACE, uap->flag));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_utimensat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, struct timespec *tptr, enum uio_seg tptrseg,
|
|
|
|
int flag)
|
2015-01-23 21:07:08 +00:00
|
|
|
{
|
|
|
|
struct nameidata nd;
|
|
|
|
struct timespec ts[2];
|
|
|
|
int error, flags;
|
|
|
|
|
2018-10-25 22:16:34 +00:00
|
|
|
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
|
2015-01-23 21:07:08 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
if ((error = getutimens(tptr, tptrseg, ts, &flags)) != 0)
|
|
|
|
return (error);
|
2015-04-04 21:47:54 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW :
|
2018-10-25 22:16:34 +00:00
|
|
|
FOLLOW) | ((flag & AT_BENEATH) != 0 ? BENEATH : 0) | AUDITVNODE1,
|
|
|
|
pathseg, path, fd, &cap_futimes_rights, td);
|
2015-01-23 21:07:08 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
|
|
|
return (error);
|
|
|
|
/*
|
|
|
|
* We are allowed to call namei() regardless of 2xUTIME_OMIT.
|
|
|
|
* POSIX states:
|
|
|
|
* "If both tv_nsec fields are UTIME_OMIT... EACCESS may be detected."
|
|
|
|
* "Search permission is denied by a component of the path prefix."
|
|
|
|
*/
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
if ((flags & UTIMENS_EXIT) == 0)
|
|
|
|
error = setutimes(td, nd.ni_vp, ts, 2, flags & UTIMENS_NULL);
|
|
|
|
vrele(nd.ni_vp);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Truncate a file given its path name.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct truncate_args {
|
|
|
|
char *path;
|
|
|
|
int pad;
|
|
|
|
off_t length;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_truncate(struct thread *td, struct truncate_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_truncate(struct thread *td, const char *path, enum uio_seg pathseg,
|
|
|
|
off_t length)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
|
|
|
struct vnode *vp;
|
2012-10-15 18:15:18 +00:00
|
|
|
void *rl_cookie;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct vattr vattr;
|
|
|
|
struct nameidata nd;
|
2012-10-22 17:50:54 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2002-09-01 20:37:28 +00:00
|
|
|
if (length < 0)
|
1994-09-02 10:23:43 +00:00
|
|
|
return(EINVAL);
|
2012-10-22 17:50:54 +00:00
|
|
|
NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, td);
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
vp = nd.ni_vp;
|
2012-10-15 18:15:18 +00:00
|
|
|
rl_cookie = vn_rangelock_wlock(vp, 0, OFF_MAX);
|
2000-07-11 22:07:57 +00:00
|
|
|
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
|
2012-10-15 18:15:18 +00:00
|
|
|
vn_rangelock_unlock(vp, rl_cookie);
|
2000-07-11 22:07:57 +00:00
|
|
|
vrele(vp);
|
|
|
|
return (error);
|
|
|
|
}
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
1994-05-24 10:09:53 +00:00
|
|
|
if (vp->v_type == VDIR)
|
|
|
|
error = EISDIR;
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
else if ((error = mac_vnode_check_write(td->td_ucred, NOCRED, vp))) {
|
2002-08-19 19:04:53 +00:00
|
|
|
}
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
else if ((error = vn_writechk(vp)) == 0 &&
|
2002-02-27 18:32:23 +00:00
|
|
|
(error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
|
1994-05-24 10:09:53 +00:00
|
|
|
VATTR_NULL(&vattr);
|
2002-09-01 20:37:28 +00:00
|
|
|
vattr.va_size = length;
|
2008-08-28 15:23:18 +00:00
|
|
|
error = VOP_SETATTR(vp, &vattr, td->td_ucred);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2012-10-15 18:15:18 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
2012-10-15 18:15:18 +00:00
|
|
|
vn_rangelock_unlock(vp, rl_cookie);
|
|
|
|
vrele(vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2004-06-11 11:16:26 +00:00
|
|
|
#if defined(COMPAT_43)
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Truncate a file given its path name.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct otruncate_args {
|
|
|
|
char *path;
|
|
|
|
long length;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-01-31 15:19:44 +00:00
|
|
|
otruncate(struct thread *td, struct otruncate_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1997-02-10 02:22:35 +00:00
|
|
|
|
2017-01-31 15:19:44 +00:00
|
|
|
return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2004-06-11 11:16:26 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
The lseek(2), mmap(2), truncate(2), ftruncate(2), pread(2), and
pwrite(2) syscalls are wrapped to provide compatibility with pre-7.x
kernels which required padding before the off_t parameter. The
fcntl(2) contains compatibility code to handle kernels before the
struct flock was changed during the 8.x CURRENT development. The
shims were reasonable to allow easier revert to the older kernel at
that time.
Now, two or three major releases later, shims do not serve any
purpose. Such old kernels cannot handle current libc, so revert the
compatibility code.
Make padded syscalls support conditional under the COMPAT6 config
option. For COMPAT32, the syscalls were under COMPAT6 already.
Remove WITHOUT_SYSCALL_COMPAT build option, which only purpose was to
(partially) disable the removed shims.
Reviewed by: jhb, imp (previous versions)
Discussed with: peter
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2015-04-18 21:50:13 +00:00
|
|
|
#if defined(COMPAT_FREEBSD6)
|
2007-07-04 22:57:21 +00:00
|
|
|
/* Versions with the pad argument */
|
|
|
|
int
|
|
|
|
freebsd6_truncate(struct thread *td, struct freebsd6_truncate_args *uap)
|
|
|
|
{
|
|
|
|
|
2017-01-31 15:19:44 +00:00
|
|
|
return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
|
2007-07-04 22:57:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd6_ftruncate(struct thread *td, struct freebsd6_ftruncate_args *uap)
|
|
|
|
{
|
|
|
|
|
2017-01-30 11:50:54 +00:00
|
|
|
return (kern_ftruncate(td, uap->fd, uap->length));
|
2007-07-04 22:57:21 +00:00
|
|
|
}
|
The lseek(2), mmap(2), truncate(2), ftruncate(2), pread(2), and
pwrite(2) syscalls are wrapped to provide compatibility with pre-7.x
kernels which required padding before the off_t parameter. The
fcntl(2) contains compatibility code to handle kernels before the
struct flock was changed during the 8.x CURRENT development. The
shims were reasonable to allow easier revert to the older kernel at
that time.
Now, two or three major releases later, shims do not serve any
purpose. Such old kernels cannot handle current libc, so revert the
compatibility code.
Make padded syscalls support conditional under the COMPAT6 config
option. For COMPAT32, the syscalls were under COMPAT6 already.
Remove WITHOUT_SYSCALL_COMPAT build option, which only purpose was to
(partially) disable the removed shims.
Reviewed by: jhb, imp (previous versions)
Discussed with: peter
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2015-04-18 21:50:13 +00:00
|
|
|
#endif
|
2007-07-04 22:57:21 +00:00
|
|
|
|
2016-08-15 20:11:52 +00:00
|
|
|
int
|
2016-08-15 19:08:51 +00:00
|
|
|
kern_fsync(struct thread *td, int fd, bool fullsync)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct vnode *vp;
|
|
|
|
struct mount *mp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct file *fp;
|
2009-06-08 21:23:54 +00:00
|
|
|
int error, lock_flags;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2016-08-15 19:08:51 +00:00
|
|
|
AUDIT_ARG_FD(fd);
|
2018-05-20 05:13:12 +00:00
|
|
|
error = getvnode(td, fd, &cap_fsync_rights, &fp);
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2003-06-22 08:41:43 +00:00
|
|
|
vp = fp->f_vnode;
|
2016-08-15 19:08:51 +00:00
|
|
|
#if 0
|
|
|
|
if (!fullsync)
|
|
|
|
/* XXXKIB: compete outstanding aio writes */;
|
|
|
|
#endif
|
2013-09-05 00:19:30 +00:00
|
|
|
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
|
|
|
|
if (error != 0)
|
2005-01-24 10:25:44 +00:00
|
|
|
goto drop;
|
2009-06-08 21:23:54 +00:00
|
|
|
if (MNT_SHARED_WRITES(mp) ||
|
|
|
|
((mp == NULL) && MNT_SHARED_WRITES(vp->v_mount))) {
|
|
|
|
lock_flags = LK_SHARED;
|
|
|
|
} else {
|
|
|
|
lock_flags = LK_EXCLUSIVE;
|
|
|
|
}
|
|
|
|
vn_lock(vp, lock_flags | LK_RETRY);
|
2009-07-28 21:52:24 +00:00
|
|
|
AUDIT_ARG_VNODE1(vp);
|
2005-01-25 00:40:01 +00:00
|
|
|
if (vp->v_object != NULL) {
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WLOCK(vp->v_object);
|
2005-01-25 00:40:01 +00:00
|
|
|
vm_object_page_clean(vp->v_object, 0, 0, 0);
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WUNLOCK(vp->v_object);
|
2001-05-19 01:28:09 +00:00
|
|
|
}
|
2016-08-15 19:08:51 +00:00
|
|
|
error = fullsync ? VOP_FSYNC(vp, MNT_WAIT, td) : VOP_FDATASYNC(vp, td);
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
2005-01-24 10:25:44 +00:00
|
|
|
drop:
|
2002-01-13 11:58:06 +00:00
|
|
|
fdrop(fp, td);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2016-08-15 19:08:51 +00:00
|
|
|
/*
|
|
|
|
* Sync an open file.
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct fsync_args {
|
|
|
|
int fd;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
|
|
|
sys_fsync(struct thread *td, struct fsync_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_fsync(td, uap->fd, true));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
sys_fdatasync(struct thread *td, struct fdatasync_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_fsync(td, uap->fd, false));
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2007-03-05 13:10:58 +00:00
|
|
|
* Rename files. Source and destination must either both be directories, or
|
|
|
|
* both not be directories. If target is a directory, it must be empty.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct rename_args {
|
|
|
|
char *from;
|
|
|
|
char *to;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_rename(struct thread *td, struct rename_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_renameat(td, AT_FDCWD, uap->from, AT_FDCWD,
|
|
|
|
uap->to, UIO_USERSPACE));
|
2002-09-01 20:37:28 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct renameat_args {
|
|
|
|
int oldfd;
|
|
|
|
char *old;
|
|
|
|
int newfd;
|
|
|
|
char *new;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_renameat(struct thread *td, struct renameat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_renameat(td, uap->oldfd, uap->old, uap->newfd, uap->new,
|
|
|
|
UIO_USERSPACE));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_renameat(struct thread *td, int oldfd, const char *old, int newfd,
|
|
|
|
const char *new, enum uio_seg pathseg)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2002-10-27 23:23:51 +00:00
|
|
|
struct mount *mp = NULL;
|
2000-07-11 22:07:57 +00:00
|
|
|
struct vnode *tvp, *fvp, *tdvp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata fromnd, tond;
|
|
|
|
int error;
|
|
|
|
|
2014-09-25 20:42:25 +00:00
|
|
|
again:
|
2000-01-10 00:08:53 +00:00
|
|
|
bwillwrite();
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
2011-08-13 09:21:16 +00:00
|
|
|
NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART |
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
AUDITVNODE1, pathseg, old, oldfd,
|
2018-05-20 05:13:12 +00:00
|
|
|
&cap_renameat_source_rights, td);
|
2002-10-19 20:25:57 +00:00
|
|
|
#else
|
2013-01-31 22:20:05 +00:00
|
|
|
NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | AUDITVNODE1,
|
2015-08-27 15:16:41 +00:00
|
|
|
pathseg, old, oldfd,
|
2018-05-20 05:13:12 +00:00
|
|
|
&cap_renameat_source_rights, td);
|
2002-10-19 20:25:57 +00:00
|
|
|
#endif
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&fromnd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_rename_from(td->td_ucred, fromnd.ni_dvp,
|
2002-10-19 20:25:57 +00:00
|
|
|
fromnd.ni_vp, &fromnd.ni_cnd);
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(fromnd.ni_dvp, 0);
|
2006-10-26 13:20:28 +00:00
|
|
|
if (fromnd.ni_dvp != fromnd.ni_vp)
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(fromnd.ni_vp, 0);
|
2002-10-19 20:25:57 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
fvp = fromnd.ni_vp;
|
2011-08-13 09:21:16 +00:00
|
|
|
NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE |
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
SAVESTART | AUDITVNODE2, pathseg, new, newfd,
|
2018-05-20 05:13:12 +00:00
|
|
|
&cap_renameat_target_rights, td);
|
1995-07-31 00:35:58 +00:00
|
|
|
if (fromnd.ni_vp->v_type == VDIR)
|
|
|
|
tond.ni_cnd.cn_flags |= WILLBEDIR;
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&tond)) != 0) {
|
1995-11-18 11:35:05 +00:00
|
|
|
/* Translate error code for rename("dir1", "dir2/."). */
|
|
|
|
if (error == EISDIR && fvp->v_type == VDIR)
|
|
|
|
error = EINVAL;
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&fromnd, NDF_ONLY_PNBUF);
|
1994-05-24 10:09:53 +00:00
|
|
|
vrele(fromnd.ni_dvp);
|
|
|
|
vrele(fvp);
|
|
|
|
goto out1;
|
|
|
|
}
|
|
|
|
tdvp = tond.ni_dvp;
|
|
|
|
tvp = tond.ni_vp;
|
2014-09-25 20:42:25 +00:00
|
|
|
error = vn_start_write(fvp, &mp, V_NOWAIT);
|
|
|
|
if (error != 0) {
|
|
|
|
NDFREE(&fromnd, NDF_ONLY_PNBUF);
|
|
|
|
NDFREE(&tond, NDF_ONLY_PNBUF);
|
|
|
|
if (tvp != NULL)
|
|
|
|
vput(tvp);
|
|
|
|
if (tdvp == tvp)
|
|
|
|
vrele(tdvp);
|
|
|
|
else
|
|
|
|
vput(tdvp);
|
|
|
|
vrele(fromnd.ni_dvp);
|
|
|
|
vrele(fvp);
|
|
|
|
vrele(tond.ni_startdir);
|
|
|
|
if (fromnd.ni_startdir != NULL)
|
|
|
|
vrele(fromnd.ni_startdir);
|
|
|
|
error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
goto again;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
if (tvp != NULL) {
|
|
|
|
if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
|
|
|
|
error = ENOTDIR;
|
|
|
|
goto out;
|
|
|
|
} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
|
|
|
|
error = EISDIR;
|
|
|
|
goto out;
|
|
|
|
}
|
Merge Capsicum overhaul:
- Capability is no longer separate descriptor type. Now every descriptor
has set of its own capability rights.
- The cap_new(2) system call is left, but it is no longer documented and
should not be used in new code.
- The new syscall cap_rights_limit(2) should be used instead of
cap_new(2), which limits capability rights of the given descriptor
without creating a new one.
- The cap_getrights(2) syscall is renamed to cap_rights_get(2).
- If CAP_IOCTL capability right is present we can further reduce allowed
ioctls list with the new cap_ioctls_limit(2) syscall. List of allowed
ioctls can be retrived with cap_ioctls_get(2) syscall.
- If CAP_FCNTL capability right is present we can further reduce fcntls
that can be used with the new cap_fcntls_limit(2) syscall and retrive
them with cap_fcntls_get(2).
- To support ioctl and fcntl white-listing the filedesc structure was
heavly modified.
- The audit subsystem, kdump and procstat tools were updated to
recognize new syscalls.
- Capability rights were revised and eventhough I tried hard to provide
backward API and ABI compatibility there are some incompatible changes
that are described in detail below:
CAP_CREATE old behaviour:
- Allow for openat(2)+O_CREAT.
- Allow for linkat(2).
- Allow for symlinkat(2).
CAP_CREATE new behaviour:
- Allow for openat(2)+O_CREAT.
Added CAP_LINKAT:
- Allow for linkat(2). ABI: Reuses CAP_RMDIR bit.
- Allow to be target for renameat(2).
Added CAP_SYMLINKAT:
- Allow for symlinkat(2).
Removed CAP_DELETE. Old behaviour:
- Allow for unlinkat(2) when removing non-directory object.
- Allow to be source for renameat(2).
Removed CAP_RMDIR. Old behaviour:
- Allow for unlinkat(2) when removing directory.
Added CAP_RENAMEAT:
- Required for source directory for the renameat(2) syscall.
Added CAP_UNLINKAT (effectively it replaces CAP_DELETE and CAP_RMDIR):
- Allow for unlinkat(2) on any object.
- Required if target of renameat(2) exists and will be removed by this
call.
Removed CAP_MAPEXEC.
CAP_MMAP old behaviour:
- Allow for mmap(2) with any combination of PROT_NONE, PROT_READ and
PROT_WRITE.
CAP_MMAP new behaviour:
- Allow for mmap(2)+PROT_NONE.
Added CAP_MMAP_R:
- Allow for mmap(PROT_READ).
Added CAP_MMAP_W:
- Allow for mmap(PROT_WRITE).
Added CAP_MMAP_X:
- Allow for mmap(PROT_EXEC).
Added CAP_MMAP_RW:
- Allow for mmap(PROT_READ | PROT_WRITE).
Added CAP_MMAP_RX:
- Allow for mmap(PROT_READ | PROT_EXEC).
Added CAP_MMAP_WX:
- Allow for mmap(PROT_WRITE | PROT_EXEC).
Added CAP_MMAP_RWX:
- Allow for mmap(PROT_READ | PROT_WRITE | PROT_EXEC).
Renamed CAP_MKDIR to CAP_MKDIRAT.
Renamed CAP_MKFIFO to CAP_MKFIFOAT.
Renamed CAP_MKNODE to CAP_MKNODEAT.
CAP_READ old behaviour:
- Allow pread(2).
- Disallow read(2), readv(2) (if there is no CAP_SEEK).
CAP_READ new behaviour:
- Allow read(2), readv(2).
- Disallow pread(2) (CAP_SEEK was also required).
CAP_WRITE old behaviour:
- Allow pwrite(2).
- Disallow write(2), writev(2) (if there is no CAP_SEEK).
CAP_WRITE new behaviour:
- Allow write(2), writev(2).
- Disallow pwrite(2) (CAP_SEEK was also required).
Added convinient defines:
#define CAP_PREAD (CAP_SEEK | CAP_READ)
#define CAP_PWRITE (CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ)
#define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL)
#define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W)
#define CAP_MMAP_RX (CAP_MMAP_R | CAP_MMAP_X)
#define CAP_MMAP_WX (CAP_MMAP_W | CAP_MMAP_X)
#define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
#define CAP_RECV CAP_READ
#define CAP_SEND CAP_WRITE
#define CAP_SOCK_CLIENT \
(CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
#define CAP_SOCK_SERVER \
(CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \
CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \
CAP_SETSOCKOPT | CAP_SHUTDOWN)
Added defines for backward API compatibility:
#define CAP_MAPEXEC CAP_MMAP_X
#define CAP_DELETE CAP_UNLINKAT
#define CAP_MKDIR CAP_MKDIRAT
#define CAP_RMDIR CAP_UNLINKAT
#define CAP_MKFIFO CAP_MKFIFOAT
#define CAP_MKNOD CAP_MKNODAT
#define CAP_SOCK_ALL (CAP_SOCK_CLIENT | CAP_SOCK_SERVER)
Sponsored by: The FreeBSD Foundation
Reviewed by: Christoph Mallon <christoph.mallon@gmx.de>
Many aspects discussed with: rwatson, benl, jonathan
ABI compatibility discussed with: kib
2013-03-02 00:53:12 +00:00
|
|
|
#ifdef CAPABILITIES
|
2019-02-08 04:18:17 +00:00
|
|
|
if (newfd != AT_FDCWD && (tond.ni_resflags & NIRES_ABS) == 0) {
|
2013-03-02 09:58:47 +00:00
|
|
|
/*
|
|
|
|
* If the target already exists we require CAP_UNLINKAT
|
2019-02-08 04:18:17 +00:00
|
|
|
* from 'newfd', when newfd was used for the lookup.
|
2013-03-02 09:58:47 +00:00
|
|
|
*/
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
error = cap_check(&tond.ni_filecaps.fc_rights,
|
2018-05-20 05:13:12 +00:00
|
|
|
&cap_unlinkat_rights);
|
2013-03-02 09:58:47 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto out;
|
|
|
|
}
|
Merge Capsicum overhaul:
- Capability is no longer separate descriptor type. Now every descriptor
has set of its own capability rights.
- The cap_new(2) system call is left, but it is no longer documented and
should not be used in new code.
- The new syscall cap_rights_limit(2) should be used instead of
cap_new(2), which limits capability rights of the given descriptor
without creating a new one.
- The cap_getrights(2) syscall is renamed to cap_rights_get(2).
- If CAP_IOCTL capability right is present we can further reduce allowed
ioctls list with the new cap_ioctls_limit(2) syscall. List of allowed
ioctls can be retrived with cap_ioctls_get(2) syscall.
- If CAP_FCNTL capability right is present we can further reduce fcntls
that can be used with the new cap_fcntls_limit(2) syscall and retrive
them with cap_fcntls_get(2).
- To support ioctl and fcntl white-listing the filedesc structure was
heavly modified.
- The audit subsystem, kdump and procstat tools were updated to
recognize new syscalls.
- Capability rights were revised and eventhough I tried hard to provide
backward API and ABI compatibility there are some incompatible changes
that are described in detail below:
CAP_CREATE old behaviour:
- Allow for openat(2)+O_CREAT.
- Allow for linkat(2).
- Allow for symlinkat(2).
CAP_CREATE new behaviour:
- Allow for openat(2)+O_CREAT.
Added CAP_LINKAT:
- Allow for linkat(2). ABI: Reuses CAP_RMDIR bit.
- Allow to be target for renameat(2).
Added CAP_SYMLINKAT:
- Allow for symlinkat(2).
Removed CAP_DELETE. Old behaviour:
- Allow for unlinkat(2) when removing non-directory object.
- Allow to be source for renameat(2).
Removed CAP_RMDIR. Old behaviour:
- Allow for unlinkat(2) when removing directory.
Added CAP_RENAMEAT:
- Required for source directory for the renameat(2) syscall.
Added CAP_UNLINKAT (effectively it replaces CAP_DELETE and CAP_RMDIR):
- Allow for unlinkat(2) on any object.
- Required if target of renameat(2) exists and will be removed by this
call.
Removed CAP_MAPEXEC.
CAP_MMAP old behaviour:
- Allow for mmap(2) with any combination of PROT_NONE, PROT_READ and
PROT_WRITE.
CAP_MMAP new behaviour:
- Allow for mmap(2)+PROT_NONE.
Added CAP_MMAP_R:
- Allow for mmap(PROT_READ).
Added CAP_MMAP_W:
- Allow for mmap(PROT_WRITE).
Added CAP_MMAP_X:
- Allow for mmap(PROT_EXEC).
Added CAP_MMAP_RW:
- Allow for mmap(PROT_READ | PROT_WRITE).
Added CAP_MMAP_RX:
- Allow for mmap(PROT_READ | PROT_EXEC).
Added CAP_MMAP_WX:
- Allow for mmap(PROT_WRITE | PROT_EXEC).
Added CAP_MMAP_RWX:
- Allow for mmap(PROT_READ | PROT_WRITE | PROT_EXEC).
Renamed CAP_MKDIR to CAP_MKDIRAT.
Renamed CAP_MKFIFO to CAP_MKFIFOAT.
Renamed CAP_MKNODE to CAP_MKNODEAT.
CAP_READ old behaviour:
- Allow pread(2).
- Disallow read(2), readv(2) (if there is no CAP_SEEK).
CAP_READ new behaviour:
- Allow read(2), readv(2).
- Disallow pread(2) (CAP_SEEK was also required).
CAP_WRITE old behaviour:
- Allow pwrite(2).
- Disallow write(2), writev(2) (if there is no CAP_SEEK).
CAP_WRITE new behaviour:
- Allow write(2), writev(2).
- Disallow pwrite(2) (CAP_SEEK was also required).
Added convinient defines:
#define CAP_PREAD (CAP_SEEK | CAP_READ)
#define CAP_PWRITE (CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ)
#define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL)
#define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W)
#define CAP_MMAP_RX (CAP_MMAP_R | CAP_MMAP_X)
#define CAP_MMAP_WX (CAP_MMAP_W | CAP_MMAP_X)
#define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
#define CAP_RECV CAP_READ
#define CAP_SEND CAP_WRITE
#define CAP_SOCK_CLIENT \
(CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
#define CAP_SOCK_SERVER \
(CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \
CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \
CAP_SETSOCKOPT | CAP_SHUTDOWN)
Added defines for backward API compatibility:
#define CAP_MAPEXEC CAP_MMAP_X
#define CAP_DELETE CAP_UNLINKAT
#define CAP_MKDIR CAP_MKDIRAT
#define CAP_RMDIR CAP_UNLINKAT
#define CAP_MKFIFO CAP_MKFIFOAT
#define CAP_MKNOD CAP_MKNODAT
#define CAP_SOCK_ALL (CAP_SOCK_CLIENT | CAP_SOCK_SERVER)
Sponsored by: The FreeBSD Foundation
Reviewed by: Christoph Mallon <christoph.mallon@gmx.de>
Many aspects discussed with: rwatson, benl, jonathan
ABI compatibility discussed with: kib
2013-03-02 00:53:12 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2008-09-01 10:11:39 +00:00
|
|
|
if (fvp == tdvp) {
|
1994-05-24 10:09:53 +00:00
|
|
|
error = EINVAL;
|
2008-09-01 10:11:39 +00:00
|
|
|
goto out;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2002-09-10 11:09:13 +00:00
|
|
|
* If the source is the same as the destination (that is, if they
|
|
|
|
* are links to the same vnode), then there is nothing to do.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2002-09-10 11:09:13 +00:00
|
|
|
if (fvp == tvp)
|
1994-05-24 10:09:53 +00:00
|
|
|
error = -1;
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
|
|
|
else
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_rename_to(td->td_ucred, tdvp,
|
2002-10-19 20:25:57 +00:00
|
|
|
tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd);
|
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
out:
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error == 0) {
|
1994-05-24 10:09:53 +00:00
|
|
|
error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
|
2013-09-05 00:19:30 +00:00
|
|
|
tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&fromnd, NDF_ONLY_PNBUF);
|
|
|
|
NDFREE(&tond, NDF_ONLY_PNBUF);
|
1994-05-24 10:09:53 +00:00
|
|
|
} else {
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&fromnd, NDF_ONLY_PNBUF);
|
|
|
|
NDFREE(&tond, NDF_ONLY_PNBUF);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (tvp != NULL)
|
2005-04-11 09:19:08 +00:00
|
|
|
vput(tvp);
|
1994-05-24 10:09:53 +00:00
|
|
|
if (tdvp == tvp)
|
|
|
|
vrele(tdvp);
|
|
|
|
else
|
|
|
|
vput(tdvp);
|
|
|
|
vrele(fromnd.ni_dvp);
|
|
|
|
vrele(fvp);
|
|
|
|
}
|
|
|
|
vrele(tond.ni_startdir);
|
2002-10-27 23:23:51 +00:00
|
|
|
vn_finished_write(mp);
|
2005-09-01 21:46:33 +00:00
|
|
|
out1:
|
1994-05-24 10:09:53 +00:00
|
|
|
if (fromnd.ni_startdir)
|
|
|
|
vrele(fromnd.ni_startdir);
|
|
|
|
if (error == -1)
|
|
|
|
return (0);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make a directory file.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mkdir_args {
|
|
|
|
char *path;
|
|
|
|
int mode;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_mkdir(struct thread *td, struct mkdir_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2001-09-12 08:38:13 +00:00
|
|
|
|
2014-11-13 18:01:51 +00:00
|
|
|
return (kern_mkdirat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
|
|
|
|
uap->mode));
|
2001-09-12 08:38:13 +00:00
|
|
|
}
|
|
|
|
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct mkdirat_args {
|
|
|
|
int fd;
|
|
|
|
char *path;
|
|
|
|
mode_t mode;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_mkdirat(struct thread *td, struct mkdirat_args *uap)
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_mkdirat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 20:50:22 +00:00
|
|
|
kern_mkdirat(struct thread *td, int fd, const char *path, enum uio_seg segflg,
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
int mode)
|
2001-09-12 08:38:13 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
|
|
|
struct vnode *vp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct vattr vattr;
|
2013-09-05 00:19:30 +00:00
|
|
|
struct nameidata nd;
|
1994-05-24 10:09:53 +00:00
|
|
|
int error;
|
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_MODE(mode);
|
2000-07-11 22:07:57 +00:00
|
|
|
restart:
|
2000-01-10 00:08:53 +00:00
|
|
|
bwillwrite();
|
2014-12-18 10:01:12 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
|
2018-05-20 05:13:12 +00:00
|
|
|
NOCACHE, segflg, path, fd, &cap_mkdirat_rights,
|
2014-12-18 10:01:12 +00:00
|
|
|
td);
|
1995-07-31 00:35:58 +00:00
|
|
|
nd.ni_cnd.cn_flags |= WILLBEDIR;
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
vp = nd.ni_vp;
|
|
|
|
if (vp != NULL) {
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2002-06-28 20:06:47 +00:00
|
|
|
/*
|
|
|
|
* XXX namei called with LOCKPARENT but not LOCKLEAF has
|
|
|
|
* the strange behaviour of leaving the vnode unlocked
|
|
|
|
* if the target is the same vnode as the parent.
|
|
|
|
*/
|
|
|
|
if (vp == nd.ni_dvp)
|
|
|
|
vrele(nd.ni_dvp);
|
|
|
|
else
|
|
|
|
vput(nd.ni_dvp);
|
2006-02-01 00:25:26 +00:00
|
|
|
vrele(vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EEXIST);
|
|
|
|
}
|
2000-07-11 22:07:57 +00:00
|
|
|
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
|
|
|
|
return (error);
|
|
|
|
goto restart;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
VATTR_NULL(&vattr);
|
|
|
|
vattr.va_type = VDIR;
|
2001-09-12 08:38:13 +00:00
|
|
|
vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
|
2002-10-19 20:25:57 +00:00
|
|
|
&vattr);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2002-10-19 20:25:57 +00:00
|
|
|
goto out;
|
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
|
|
|
out:
|
|
|
|
#endif
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1998-05-07 04:58:58 +00:00
|
|
|
vput(nd.ni_dvp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error == 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
vput(nd.ni_vp);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove a directory file.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct rmdir_args {
|
|
|
|
char *path;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_rmdir(struct thread *td, struct rmdir_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
|
2019-04-06 09:34:26 +00:00
|
|
|
return (kern_frmdirat(td, AT_FDCWD, uap->path, FD_NONE, UIO_USERSPACE,
|
|
|
|
0));
|
Implement the
openat(2), faccessat(2), fchmodat(2), fchownat(2), fstatat(2),
futimesat(2), linkat(2), mkdirat(2), mkfifoat(2), mknodat(2),
readlinkat(2), renameat(2), symlinkat(2)
syscalls.
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
2008-03-31 12:04:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2019-04-06 09:34:26 +00:00
|
|
|
kern_frmdirat(struct thread *td, int dfd, const char *path, int fd,
|
|
|
|
enum uio_seg pathseg, int flag)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct mount *mp;
|
|
|
|
struct vnode *vp;
|
2019-04-06 09:34:26 +00:00
|
|
|
struct file *fp;
|
2013-09-05 00:19:30 +00:00
|
|
|
struct nameidata nd;
|
2019-04-06 09:34:26 +00:00
|
|
|
cap_rights_t rights;
|
1994-05-24 10:09:53 +00:00
|
|
|
int error;
|
|
|
|
|
2019-04-06 09:34:26 +00:00
|
|
|
fp = NULL;
|
|
|
|
if (fd != FD_NONE) {
|
|
|
|
error = getvnode(td, fd, cap_rights_init(&rights, CAP_LOOKUP),
|
|
|
|
&fp);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2000-07-11 22:07:57 +00:00
|
|
|
restart:
|
2000-01-10 00:08:53 +00:00
|
|
|
bwillwrite();
|
2018-10-25 22:16:34 +00:00
|
|
|
NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 |
|
|
|
|
((flag & AT_BENEATH) != 0 ? BENEATH : 0),
|
2019-04-06 09:34:26 +00:00
|
|
|
pathseg, path, dfd, &cap_unlinkat_rights, td);
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
2019-04-06 09:34:26 +00:00
|
|
|
goto fdout;
|
1994-05-24 10:09:53 +00:00
|
|
|
vp = nd.ni_vp;
|
|
|
|
if (vp->v_type != VDIR) {
|
|
|
|
error = ENOTDIR;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* No rmdir "." please.
|
|
|
|
*/
|
|
|
|
if (nd.ni_dvp == vp) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* The root of a mounted filesystem cannot be deleted.
|
|
|
|
*/
|
2002-08-04 10:29:36 +00:00
|
|
|
if (vp->v_vflag & VV_ROOT) {
|
1994-05-24 10:09:53 +00:00
|
|
|
error = EBUSY;
|
2000-07-11 22:07:57 +00:00
|
|
|
goto out;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2019-04-06 09:34:26 +00:00
|
|
|
|
|
|
|
if (fp != NULL && fp->f_vnode != vp) {
|
|
|
|
if ((fp->f_vnode->v_iflag & VI_DOOMED) != 0)
|
|
|
|
error = EBADF;
|
|
|
|
else
|
|
|
|
error = EDEADLK;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2002-10-19 20:25:57 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_unlink(td->td_ucred, nd.ni_dvp, vp,
|
2002-10-19 20:25:57 +00:00
|
|
|
&nd.ni_cnd);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2002-10-19 20:25:57 +00:00
|
|
|
goto out;
|
|
|
|
#endif
|
2000-07-11 22:07:57 +00:00
|
|
|
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2006-02-01 00:25:26 +00:00
|
|
|
vput(vp);
|
2000-07-11 22:07:57 +00:00
|
|
|
if (nd.ni_dvp == vp)
|
|
|
|
vrele(nd.ni_dvp);
|
|
|
|
else
|
|
|
|
vput(nd.ni_dvp);
|
|
|
|
if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
|
2019-04-06 09:34:26 +00:00
|
|
|
goto fdout;
|
2000-07-11 22:07:57 +00:00
|
|
|
goto restart;
|
|
|
|
}
|
2013-05-11 11:17:44 +00:00
|
|
|
vfs_notify_upper(vp, VFS_NOTIFY_UPPER_UNLINK);
|
2000-07-11 22:07:57 +00:00
|
|
|
error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
|
|
|
|
vn_finished_write(mp);
|
1999-12-15 23:02:35 +00:00
|
|
|
out:
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2006-02-01 00:25:26 +00:00
|
|
|
vput(vp);
|
1998-05-07 04:58:58 +00:00
|
|
|
if (nd.ni_dvp == vp)
|
|
|
|
vrele(nd.ni_dvp);
|
|
|
|
else
|
|
|
|
vput(nd.ni_dvp);
|
2019-04-06 09:34:26 +00:00
|
|
|
fdout:
|
|
|
|
if (fp != NULL)
|
|
|
|
fdrop(fp, td);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
#if defined(COMPAT_43) || defined(COMPAT_FREEBSD11)
|
|
|
|
int
|
|
|
|
freebsd11_kern_getdirentries(struct thread *td, int fd, char *ubuf, u_int count,
|
|
|
|
long *basep, void (*func)(struct freebsd11_dirent *))
|
|
|
|
{
|
|
|
|
struct freebsd11_dirent dstdp;
|
|
|
|
struct dirent *dp, *edp;
|
|
|
|
char *dirbuf;
|
|
|
|
off_t base;
|
|
|
|
ssize_t resid, ucount;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
/* XXX arbitrary sanity limit on `count'. */
|
|
|
|
count = min(count, 64 * 1024);
|
|
|
|
|
|
|
|
dirbuf = malloc(count, M_TEMP, M_WAITOK);
|
|
|
|
|
|
|
|
error = kern_getdirentries(td, fd, dirbuf, count, &base, &resid,
|
|
|
|
UIO_SYSSPACE);
|
|
|
|
if (error != 0)
|
|
|
|
goto done;
|
|
|
|
if (basep != NULL)
|
|
|
|
*basep = base;
|
|
|
|
|
|
|
|
ucount = 0;
|
|
|
|
for (dp = (struct dirent *)dirbuf,
|
|
|
|
edp = (struct dirent *)&dirbuf[count - resid];
|
|
|
|
ucount < count && dp < edp; ) {
|
|
|
|
if (dp->d_reclen == 0)
|
|
|
|
break;
|
|
|
|
MPASS(dp->d_reclen >= _GENERIC_DIRLEN(0));
|
|
|
|
if (dp->d_namlen >= sizeof(dstdp.d_name))
|
|
|
|
continue;
|
|
|
|
dstdp.d_type = dp->d_type;
|
|
|
|
dstdp.d_namlen = dp->d_namlen;
|
|
|
|
dstdp.d_fileno = dp->d_fileno; /* truncate */
|
2017-06-09 11:17:08 +00:00
|
|
|
if (dstdp.d_fileno != dp->d_fileno) {
|
|
|
|
switch (ino64_trunc_error) {
|
|
|
|
default:
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
error = EOVERFLOW;
|
|
|
|
goto done;
|
|
|
|
case 2:
|
|
|
|
dstdp.d_fileno = UINT32_MAX;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
dstdp.d_reclen = sizeof(dstdp) - sizeof(dstdp.d_name) +
|
|
|
|
((dp->d_namlen + 1 + 3) &~ 3);
|
|
|
|
bcopy(dp->d_name, dstdp.d_name, dstdp.d_namlen);
|
|
|
|
bzero(dstdp.d_name + dstdp.d_namlen,
|
|
|
|
dstdp.d_reclen - offsetof(struct freebsd11_dirent, d_name) -
|
|
|
|
dstdp.d_namlen);
|
|
|
|
MPASS(dstdp.d_reclen <= dp->d_reclen);
|
|
|
|
MPASS(ucount + dstdp.d_reclen <= count);
|
|
|
|
if (func != NULL)
|
|
|
|
func(&dstdp);
|
|
|
|
error = copyout(&dstdp, ubuf + ucount, dstdp.d_reclen);
|
|
|
|
if (error != 0)
|
|
|
|
break;
|
|
|
|
dp = (struct dirent *)((char *)dp + dp->d_reclen);
|
|
|
|
ucount += dstdp.d_reclen;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
free(dirbuf, M_TEMP);
|
|
|
|
if (error == 0)
|
|
|
|
td->td_retval[0] = ucount;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif /* COMPAT */
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#ifdef COMPAT_43
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
static void
|
|
|
|
ogetdirentries_cvt(struct freebsd11_dirent *dp)
|
|
|
|
{
|
|
|
|
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
|
|
|
/*
|
|
|
|
* The expected low byte of dp->d_namlen is our dp->d_type.
|
|
|
|
* The high MBZ byte of dp->d_namlen is our dp->d_namlen.
|
|
|
|
*/
|
|
|
|
dp->d_type = dp->d_namlen;
|
|
|
|
dp->d_namlen = 0;
|
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* The dp->d_type is the high byte of the expected dp->d_namlen,
|
|
|
|
* so must be zero'ed.
|
|
|
|
*/
|
|
|
|
dp->d_type = 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2002-05-16 21:28:32 +00:00
|
|
|
* Read a block of directory entries in a filesystem independent format.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct ogetdirentries_args {
|
|
|
|
int fd;
|
|
|
|
char *buf;
|
|
|
|
u_int count;
|
|
|
|
long *basep;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2011-04-01 11:16:29 +00:00
|
|
|
ogetdirentries(struct thread *td, struct ogetdirentries_args *uap)
|
|
|
|
{
|
|
|
|
long loff;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = kern_ogetdirentries(td, uap, &loff);
|
|
|
|
if (error == 0)
|
|
|
|
error = copyout(&loff, uap->basep, sizeof(long));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
|
|
|
|
long *ploff)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
long base;
|
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2001-08-10 22:14:18 +00:00
|
|
|
/* XXX arbitrary sanity limit on `count'. */
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->count > 64 * 1024)
|
2001-08-10 22:14:18 +00:00
|
|
|
return (EINVAL);
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
|
|
|
|
error = freebsd11_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
|
|
|
|
&base, ogetdirentries_cvt);
|
|
|
|
|
|
|
|
if (error == 0 && uap->basep != NULL)
|
|
|
|
error = copyout(&base, uap->basep, sizeof(long));
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
1997-02-10 02:22:35 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
#if defined(COMPAT_FREEBSD11)
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
struct freebsd11_getdirentries_args {
|
1994-05-24 10:09:53 +00:00
|
|
|
int fd;
|
|
|
|
char *buf;
|
|
|
|
u_int count;
|
|
|
|
long *basep;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
freebsd11_getdirentries(struct thread *td,
|
|
|
|
struct freebsd11_getdirentries_args *uap)
|
2008-10-22 21:55:48 +00:00
|
|
|
{
|
|
|
|
long base;
|
|
|
|
int error;
|
|
|
|
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
error = freebsd11_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
|
|
|
|
&base, NULL);
|
|
|
|
|
|
|
|
if (error == 0 && uap->basep != NULL)
|
|
|
|
error = copyout(&base, uap->basep, sizeof(long));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd11_getdents(struct thread *td, struct freebsd11_getdents_args *uap)
|
|
|
|
{
|
|
|
|
struct freebsd11_getdirentries_args ap;
|
|
|
|
|
|
|
|
ap.fd = uap->fd;
|
|
|
|
ap.buf = uap->buf;
|
|
|
|
ap.count = uap->count;
|
|
|
|
ap.basep = NULL;
|
|
|
|
return (freebsd11_getdirentries(td, &ap));
|
|
|
|
}
|
|
|
|
#endif /* COMPAT_FREEBSD11 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read a block of directory entries in a filesystem independent format.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
sys_getdirentries(struct thread *td, struct getdirentries_args *uap)
|
|
|
|
{
|
|
|
|
off_t base;
|
|
|
|
int error;
|
|
|
|
|
2012-05-24 08:00:26 +00:00
|
|
|
error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base,
|
|
|
|
NULL, UIO_USERSPACE);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2008-10-22 21:55:48 +00:00
|
|
|
return (error);
|
|
|
|
if (uap->basep != NULL)
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
error = copyout(&base, uap->basep, sizeof(off_t));
|
2008-10-22 21:55:48 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
kern_getdirentries(struct thread *td, int fd, char *buf, size_t count,
|
|
|
|
off_t *basep, ssize_t *residp, enum uio_seg bufseg)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1998-11-03 08:01:48 +00:00
|
|
|
struct vnode *vp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct file *fp;
|
|
|
|
struct uio auio;
|
|
|
|
struct iovec aiov;
|
Commit the 64-bit inode project.
Extend the ino_t, dev_t, nlink_t types to 64-bit ints. Modify
struct dirent layout to add d_off, increase the size of d_fileno
to 64-bits, increase the size of d_namlen to 16-bits, and change
the required alignment. Increase struct statfs f_mntfromname[] and
f_mntonname[] array length MNAMELEN to 1024.
ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and
by employing other tricks. Unfortunately, not everything can be
fixed, especially outside the base system. For instance, third-party
APIs which pass struct stat around are broken in backward and
forward incompatible ways.
Kinfo sysctl MIBs ABI is changed in backward-compatible way, but
there is no general mechanism to handle other sysctl MIBS which
return structures where the layout has changed. It was considered
that the breakage is either in the management interfaces, where we
usually allow ABI slip, or is not important.
Struct xvnode changed layout, no compat shims are provided.
For struct xtty, dev_t tty device member was reduced to uint32_t.
It was decided that keeping ABI compat in this case is more useful
than reporting 64-bit dev_t, for the sake of pstat.
Update note: strictly follow the instructions in UPDATING. Build
and install the new kernel with COMPAT_FREEBSD11 option enabled,
then reboot, and only then install new world.
Credits: The 64-bit inode project, also known as ino64, started life
many years ago as a project by Gleb Kurtsou (gleb). Kirk McKusick
(mckusick) then picked up and updated the patch, and acted as a
flag-waver. Feedback, suggestions, and discussions were carried
by Ed Maste (emaste), John Baldwin (jhb), Jilles Tjoelker (jilles),
and Rick Macklem (rmacklem). Kris Moore (kris) performed an initial
ports investigation followed by an exp-run by Antoine Brodin (antoine).
Essential and all-embracing testing was done by Peter Holm (pho).
The heavy lifting of coordinating all these efforts and bringing the
project to completion were done by Konstantin Belousov (kib).
Sponsored by: The FreeBSD Foundation (emaste, kib)
Differential revision: https://reviews.freebsd.org/D10439
2017-05-23 09:29:05 +00:00
|
|
|
off_t loff;
|
1997-02-10 02:22:35 +00:00
|
|
|
int error, eofflag;
|
2012-07-02 21:01:03 +00:00
|
|
|
off_t foffset;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_FD(fd);
|
2012-03-09 21:31:12 +00:00
|
|
|
if (count > IOSIZE_MAX)
|
2008-12-27 10:13:43 +00:00
|
|
|
return (EINVAL);
|
2012-03-09 21:31:12 +00:00
|
|
|
auio.uio_resid = count;
|
2018-05-09 18:47:24 +00:00
|
|
|
error = getvnode(td, fd, &cap_read_rights, &fp);
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
if (error != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
2002-01-13 11:58:06 +00:00
|
|
|
if ((fp->f_flag & FREAD) == 0) {
|
|
|
|
fdrop(fp, td);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EBADF);
|
2002-01-13 11:58:06 +00:00
|
|
|
}
|
2003-06-22 08:41:43 +00:00
|
|
|
vp = fp->f_vnode;
|
2012-07-02 21:01:03 +00:00
|
|
|
foffset = foffset_lock(fp, 0);
|
1994-05-24 10:09:53 +00:00
|
|
|
unionread:
|
2002-01-13 11:58:06 +00:00
|
|
|
if (vp->v_type != VDIR) {
|
2005-01-24 10:25:44 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
2002-01-13 11:58:06 +00:00
|
|
|
}
|
2008-10-22 21:55:48 +00:00
|
|
|
aiov.iov_base = buf;
|
|
|
|
aiov.iov_len = count;
|
1994-05-24 10:09:53 +00:00
|
|
|
auio.uio_iov = &aiov;
|
|
|
|
auio.uio_iovcnt = 1;
|
|
|
|
auio.uio_rw = UIO_READ;
|
2012-05-24 08:00:26 +00:00
|
|
|
auio.uio_segflg = bufseg;
|
2001-09-12 08:38:13 +00:00
|
|
|
auio.uio_td = td;
|
2009-02-13 18:18:14 +00:00
|
|
|
vn_lock(vp, LK_SHARED | LK_RETRY);
|
2009-07-28 21:52:24 +00:00
|
|
|
AUDIT_ARG_VNODE1(vp);
|
2012-07-02 21:01:03 +00:00
|
|
|
loff = auio.uio_offset = foffset;
|
2002-08-01 20:44:52 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_readdir(td->td_ucred, vp);
|
2002-08-01 20:44:52 +00:00
|
|
|
if (error == 0)
|
|
|
|
#endif
|
|
|
|
error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL,
|
|
|
|
NULL);
|
2012-07-02 21:01:03 +00:00
|
|
|
foffset = auio.uio_offset;
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0) {
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2007-02-19 10:56:09 +00:00
|
|
|
goto fail;
|
|
|
|
}
|
2008-10-22 21:55:48 +00:00
|
|
|
if (count == auio.uio_resid &&
|
2007-02-19 10:56:09 +00:00
|
|
|
(vp->v_vflag & VV_ROOT) &&
|
|
|
|
(vp->v_mount->mnt_flag & MNT_UNION)) {
|
|
|
|
struct vnode *tvp = vp;
|
2013-09-05 00:19:30 +00:00
|
|
|
|
2007-02-19 10:56:09 +00:00
|
|
|
vp = vp->v_mount->mnt_vnodecovered;
|
|
|
|
VREF(vp);
|
|
|
|
fp->f_vnode = vp;
|
|
|
|
fp->f_data = vp;
|
2012-07-02 21:01:03 +00:00
|
|
|
foffset = 0;
|
2007-02-19 10:56:09 +00:00
|
|
|
vput(tvp);
|
|
|
|
goto unionread;
|
1999-02-27 07:06:05 +00:00
|
|
|
}
|
2008-01-13 14:44:15 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2008-10-22 21:55:48 +00:00
|
|
|
*basep = loff;
|
2012-05-24 08:00:26 +00:00
|
|
|
if (residp != NULL)
|
|
|
|
*residp = auio.uio_resid;
|
2008-10-22 21:55:48 +00:00
|
|
|
td->td_retval[0] = count - auio.uio_resid;
|
2005-01-24 10:25:44 +00:00
|
|
|
fail:
|
2012-07-02 21:01:03 +00:00
|
|
|
foffset_unlock(fp, foffset, 0);
|
2002-01-13 11:58:06 +00:00
|
|
|
fdrop(fp, td);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
2007-03-05 13:10:58 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Set the mode mask for creation of filesystem nodes.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct umask_args {
|
|
|
|
int newmask;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1997-02-10 02:22:35 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_umask(struct thread *td, struct umask_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2015-05-18 13:43:33 +00:00
|
|
|
struct filedesc *fdp;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2001-09-12 08:38:13 +00:00
|
|
|
fdp = td->td_proc->p_fd;
|
2015-05-18 13:43:33 +00:00
|
|
|
FILEDESC_XLOCK(fdp);
|
2001-09-12 08:38:13 +00:00
|
|
|
td->td_retval[0] = fdp->fd_cmask;
|
2002-12-14 01:56:26 +00:00
|
|
|
fdp->fd_cmask = uap->newmask & ALLPERMS;
|
2015-05-18 13:43:33 +00:00
|
|
|
FILEDESC_XUNLOCK(fdp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-03-05 13:10:58 +00:00
|
|
|
* Void all references to file by ripping underlying filesystem away from
|
|
|
|
* vnode.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct revoke_args {
|
|
|
|
char *path;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_revoke(struct thread *td, struct revoke_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2000-07-11 22:07:57 +00:00
|
|
|
struct vnode *vp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct vattr vattr;
|
|
|
|
struct nameidata nd;
|
2013-09-05 00:19:30 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2013-01-31 22:20:05 +00:00
|
|
|
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
|
|
|
|
uap->path, td);
|
1999-01-27 21:50:00 +00:00
|
|
|
if ((error = namei(&nd)) != 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
vp = nd.ni_vp;
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2010-07-06 18:20:49 +00:00
|
|
|
if (vp->v_type != VCHR || vp->v_rdev == NULL) {
|
2005-01-24 10:25:44 +00:00
|
|
|
error = EINVAL;
|
2005-03-13 11:45:51 +00:00
|
|
|
goto out;
|
1999-01-24 06:28:37 +00:00
|
|
|
}
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_vnode_check_revoke(td->td_ucred, vp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2005-03-13 11:45:51 +00:00
|
|
|
goto out;
|
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-01 15:37:12 +00:00
|
|
|
#endif
|
2008-08-28 15:23:18 +00:00
|
|
|
error = VOP_GETATTR(vp, &vattr, td->td_ucred);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2005-03-13 11:45:51 +00:00
|
|
|
goto out;
|
2002-02-27 18:32:23 +00:00
|
|
|
if (td->td_ucred->cr_uid != vattr.va_uid) {
|
2007-06-12 00:12:01 +00:00
|
|
|
error = priv_check(td, PRIV_VFS_ADMIN);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2005-03-13 11:45:51 +00:00
|
|
|
goto out;
|
2001-10-01 20:01:07 +00:00
|
|
|
}
|
1999-08-26 14:53:31 +00:00
|
|
|
if (vcount(vp) > 1)
|
1997-02-10 02:22:35 +00:00
|
|
|
VOP_REVOKE(vp, REVOKEALL);
|
2005-03-13 11:45:51 +00:00
|
|
|
out:
|
2005-01-24 10:25:44 +00:00
|
|
|
vput(vp);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-08-11 12:30:23 +00:00
|
|
|
* Convert a user file descriptor to a kernel file entry and check that, if it
|
|
|
|
* is a capability, the correct rights are present. A reference on the file
|
|
|
|
* entry is held upon returning.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2015-06-16 13:09:18 +00:00
|
|
|
getvnode(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct file *fp;
|
2011-08-11 12:30:23 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2015-06-16 13:09:18 +00:00
|
|
|
error = fget_unlocked(td->td_proc->p_fd, fd, rightsp, &fp, NULL);
|
Merge Capsicum overhaul:
- Capability is no longer separate descriptor type. Now every descriptor
has set of its own capability rights.
- The cap_new(2) system call is left, but it is no longer documented and
should not be used in new code.
- The new syscall cap_rights_limit(2) should be used instead of
cap_new(2), which limits capability rights of the given descriptor
without creating a new one.
- The cap_getrights(2) syscall is renamed to cap_rights_get(2).
- If CAP_IOCTL capability right is present we can further reduce allowed
ioctls list with the new cap_ioctls_limit(2) syscall. List of allowed
ioctls can be retrived with cap_ioctls_get(2) syscall.
- If CAP_FCNTL capability right is present we can further reduce fcntls
that can be used with the new cap_fcntls_limit(2) syscall and retrive
them with cap_fcntls_get(2).
- To support ioctl and fcntl white-listing the filedesc structure was
heavly modified.
- The audit subsystem, kdump and procstat tools were updated to
recognize new syscalls.
- Capability rights were revised and eventhough I tried hard to provide
backward API and ABI compatibility there are some incompatible changes
that are described in detail below:
CAP_CREATE old behaviour:
- Allow for openat(2)+O_CREAT.
- Allow for linkat(2).
- Allow for symlinkat(2).
CAP_CREATE new behaviour:
- Allow for openat(2)+O_CREAT.
Added CAP_LINKAT:
- Allow for linkat(2). ABI: Reuses CAP_RMDIR bit.
- Allow to be target for renameat(2).
Added CAP_SYMLINKAT:
- Allow for symlinkat(2).
Removed CAP_DELETE. Old behaviour:
- Allow for unlinkat(2) when removing non-directory object.
- Allow to be source for renameat(2).
Removed CAP_RMDIR. Old behaviour:
- Allow for unlinkat(2) when removing directory.
Added CAP_RENAMEAT:
- Required for source directory for the renameat(2) syscall.
Added CAP_UNLINKAT (effectively it replaces CAP_DELETE and CAP_RMDIR):
- Allow for unlinkat(2) on any object.
- Required if target of renameat(2) exists and will be removed by this
call.
Removed CAP_MAPEXEC.
CAP_MMAP old behaviour:
- Allow for mmap(2) with any combination of PROT_NONE, PROT_READ and
PROT_WRITE.
CAP_MMAP new behaviour:
- Allow for mmap(2)+PROT_NONE.
Added CAP_MMAP_R:
- Allow for mmap(PROT_READ).
Added CAP_MMAP_W:
- Allow for mmap(PROT_WRITE).
Added CAP_MMAP_X:
- Allow for mmap(PROT_EXEC).
Added CAP_MMAP_RW:
- Allow for mmap(PROT_READ | PROT_WRITE).
Added CAP_MMAP_RX:
- Allow for mmap(PROT_READ | PROT_EXEC).
Added CAP_MMAP_WX:
- Allow for mmap(PROT_WRITE | PROT_EXEC).
Added CAP_MMAP_RWX:
- Allow for mmap(PROT_READ | PROT_WRITE | PROT_EXEC).
Renamed CAP_MKDIR to CAP_MKDIRAT.
Renamed CAP_MKFIFO to CAP_MKFIFOAT.
Renamed CAP_MKNODE to CAP_MKNODEAT.
CAP_READ old behaviour:
- Allow pread(2).
- Disallow read(2), readv(2) (if there is no CAP_SEEK).
CAP_READ new behaviour:
- Allow read(2), readv(2).
- Disallow pread(2) (CAP_SEEK was also required).
CAP_WRITE old behaviour:
- Allow pwrite(2).
- Disallow write(2), writev(2) (if there is no CAP_SEEK).
CAP_WRITE new behaviour:
- Allow write(2), writev(2).
- Disallow pwrite(2) (CAP_SEEK was also required).
Added convinient defines:
#define CAP_PREAD (CAP_SEEK | CAP_READ)
#define CAP_PWRITE (CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ)
#define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL)
#define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W)
#define CAP_MMAP_RX (CAP_MMAP_R | CAP_MMAP_X)
#define CAP_MMAP_WX (CAP_MMAP_W | CAP_MMAP_X)
#define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
#define CAP_RECV CAP_READ
#define CAP_SEND CAP_WRITE
#define CAP_SOCK_CLIENT \
(CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
#define CAP_SOCK_SERVER \
(CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \
CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \
CAP_SETSOCKOPT | CAP_SHUTDOWN)
Added defines for backward API compatibility:
#define CAP_MAPEXEC CAP_MMAP_X
#define CAP_DELETE CAP_UNLINKAT
#define CAP_MKDIR CAP_MKDIRAT
#define CAP_RMDIR CAP_UNLINKAT
#define CAP_MKFIFO CAP_MKFIFOAT
#define CAP_MKNOD CAP_MKNODAT
#define CAP_SOCK_ALL (CAP_SOCK_CLIENT | CAP_SOCK_SERVER)
Sponsored by: The FreeBSD Foundation
Reviewed by: Christoph Mallon <christoph.mallon@gmx.de>
Many aspects discussed with: rwatson, benl, jonathan
ABI compatibility discussed with: kib
2013-03-02 00:53:12 +00:00
|
|
|
if (error != 0)
|
2011-08-11 12:30:23 +00:00
|
|
|
return (error);
|
2011-11-24 20:34:06 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The file could be not of the vnode type, or it may be not
|
|
|
|
* yet fully initialized, in which case the f_vnode pointer
|
|
|
|
* may be set, but f_ops is still badfileops. E.g.,
|
|
|
|
* devfs_open() transiently create such situation to
|
|
|
|
* facilitate csw d_fdopen().
|
|
|
|
*
|
|
|
|
* Dupfdopen() handling in kern_openat() installs the
|
|
|
|
* half-baked file into the process descriptor table, allowing
|
|
|
|
* other thread to dereference it. Guard against the race by
|
|
|
|
* checking f_ops.
|
|
|
|
*/
|
|
|
|
if (fp->f_vnode == NULL || fp->f_ops == &badfileops) {
|
2015-06-16 13:09:18 +00:00
|
|
|
fdrop(fp, td);
|
2011-08-11 12:30:23 +00:00
|
|
|
return (EINVAL);
|
2002-01-13 11:58:06 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
*fpp = fp;
|
2011-08-11 12:30:23 +00:00
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2003-07-04 12:20:27 +00:00
|
|
|
|
2011-08-11 12:30:23 +00:00
|
|
|
|
1999-09-11 00:46:08 +00:00
|
|
|
/*
|
2007-03-05 13:10:58 +00:00
|
|
|
* Get an (NFS) file handle.
|
1999-09-11 00:46:08 +00:00
|
|
|
*/
|
2004-04-05 10:15:53 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct lgetfh_args {
|
2018-12-07 15:17:29 +00:00
|
|
|
char *fname;
|
2004-04-05 10:15:53 +00:00
|
|
|
fhandle_t *fhp;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_lgetfh(struct thread *td, struct lgetfh_args *uap)
|
2018-12-07 15:17:29 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_getfhat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->fname,
|
|
|
|
UIO_USERSPACE, uap->fhp));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct getfh_args {
|
|
|
|
char *fname;
|
|
|
|
fhandle_t *fhp;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
|
|
|
sys_getfh(struct thread *td, struct getfh_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_getfhat(td, 0, AT_FDCWD, uap->fname, UIO_USERSPACE,
|
|
|
|
uap->fhp));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* syscall for the rpc.lockd to use to translate an open descriptor into
|
|
|
|
* a NFS file handle.
|
|
|
|
*
|
|
|
|
* warning: do not remove the priv_check() call or this becomes one giant
|
|
|
|
* security hole.
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct getfhat_args {
|
|
|
|
int fd;
|
|
|
|
char *path;
|
|
|
|
fhandle_t *fhp;
|
|
|
|
int flags;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
|
|
|
sys_getfhat(struct thread *td, struct getfhat_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((uap->flags & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
|
2019-01-09 17:23:59 +00:00
|
|
|
return (EINVAL);
|
2018-12-11 02:48:49 +00:00
|
|
|
return (kern_getfhat(td, uap->flags, uap->fd, uap->path, UIO_USERSPACE,
|
|
|
|
uap->fhp));
|
2018-12-07 15:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
kern_getfhat(struct thread *td, int flags, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, fhandle_t *fhp)
|
2004-04-05 10:15:53 +00:00
|
|
|
{
|
|
|
|
struct nameidata nd;
|
|
|
|
fhandle_t fh;
|
2017-05-17 00:34:34 +00:00
|
|
|
struct vnode *vp;
|
2004-04-05 10:15:53 +00:00
|
|
|
int error;
|
|
|
|
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_VFS_GETFH);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2004-04-05 10:15:53 +00:00
|
|
|
return (error);
|
2018-12-07 15:17:29 +00:00
|
|
|
NDINIT_AT(&nd, LOOKUP, ((flags & AT_SYMLINK_NOFOLLOW) != 0 ? NOFOLLOW :
|
|
|
|
FOLLOW) | ((flags & AT_BENEATH) != 0 ? BENEATH : 0) | LOCKLEAF |
|
|
|
|
AUDITVNODE1, pathseg, path, fd, td);
|
2004-04-05 10:15:53 +00:00
|
|
|
error = namei(&nd);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2004-04-05 10:15:53 +00:00
|
|
|
return (error);
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
vp = nd.ni_vp;
|
|
|
|
bzero(&fh, sizeof(fh));
|
|
|
|
fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
|
2007-02-15 22:08:35 +00:00
|
|
|
error = VOP_VPTOFH(vp, &fh.fh_fid);
|
2004-04-05 10:15:53 +00:00
|
|
|
vput(vp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error == 0)
|
2018-12-07 15:17:29 +00:00
|
|
|
error = copyout(&fh, fhp, sizeof (fh));
|
2004-04-05 10:15:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1999-09-11 00:46:08 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
2018-12-07 15:17:29 +00:00
|
|
|
struct fhlink_args {
|
1999-09-11 00:46:08 +00:00
|
|
|
fhandle_t *fhp;
|
2018-12-07 15:17:29 +00:00
|
|
|
const char *to;
|
1999-09-11 00:46:08 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2018-12-07 15:17:29 +00:00
|
|
|
sys_fhlink(struct thread *td, struct fhlink_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_fhlinkat(td, AT_FDCWD, uap->to, UIO_USERSPACE, uap->fhp));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct fhlinkat_args {
|
|
|
|
fhandle_t *fhp;
|
|
|
|
int tofd;
|
|
|
|
const char *to;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
|
|
|
sys_fhlinkat(struct thread *td, struct fhlinkat_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_fhlinkat(td, uap->tofd, uap->to, UIO_USERSPACE, uap->fhp));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
kern_fhlinkat(struct thread *td, int fd, const char *path,
|
|
|
|
enum uio_seg pathseg, fhandle_t *fhp)
|
1999-09-11 00:46:08 +00:00
|
|
|
{
|
|
|
|
fhandle_t fh;
|
2018-12-07 15:17:29 +00:00
|
|
|
struct mount *mp;
|
2017-05-17 00:34:34 +00:00
|
|
|
struct vnode *vp;
|
1999-09-11 00:46:08 +00:00
|
|
|
int error;
|
|
|
|
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_VFS_GETFH);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1999-09-11 00:46:08 +00:00
|
|
|
return (error);
|
2018-12-07 15:17:29 +00:00
|
|
|
error = copyin(fhp, &fh, sizeof(fh));
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1999-09-11 00:46:08 +00:00
|
|
|
return (error);
|
2018-12-07 15:17:29 +00:00
|
|
|
do {
|
|
|
|
bwillwrite();
|
|
|
|
if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL)
|
|
|
|
return (ESTALE);
|
|
|
|
error = VFS_FHTOVP(mp, &fh.fh_fid, LK_SHARED, &vp);
|
|
|
|
vfs_unbusy(mp);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
VOP_UNLOCK(vp, 0);
|
|
|
|
} while ((error = kern_linkat_vp(td, vp, fd, path, pathseg)) == EAGAIN);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct fhreadlink_args {
|
|
|
|
fhandle_t *fhp;
|
|
|
|
char *buf;
|
|
|
|
size_t bufsize;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
|
|
|
sys_fhreadlink(struct thread *td, struct fhreadlink_args *uap)
|
|
|
|
{
|
|
|
|
fhandle_t fh;
|
|
|
|
struct mount *mp;
|
|
|
|
struct vnode *vp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = priv_check(td, PRIV_VFS_GETFH);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
if (uap->bufsize > IOSIZE_MAX)
|
|
|
|
return (EINVAL);
|
|
|
|
error = copyin(uap->fhp, &fh, sizeof(fh));
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL)
|
|
|
|
return (ESTALE);
|
|
|
|
error = VFS_FHTOVP(mp, &fh.fh_fid, LK_SHARED, &vp);
|
|
|
|
vfs_unbusy(mp);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
error = kern_readlink_vp(vp, uap->buf, UIO_USERSPACE, uap->bufsize, td);
|
1999-09-11 00:46:08 +00:00
|
|
|
vput(vp);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-11-06 13:42:10 +00:00
|
|
|
* syscall for the rpc.lockd to use to translate a NFS file handle into an
|
|
|
|
* open descriptor.
|
1999-09-11 00:46:08 +00:00
|
|
|
*
|
2006-11-06 13:42:10 +00:00
|
|
|
* warning: do not remove the priv_check() call or this becomes one giant
|
1999-09-11 00:46:08 +00:00
|
|
|
* security hole.
|
|
|
|
*/
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct fhopen_args {
|
|
|
|
const struct fhandle *u_fhp;
|
|
|
|
int flags;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_fhopen(struct thread *td, struct fhopen_args *uap)
|
1999-09-11 00:46:08 +00:00
|
|
|
{
|
|
|
|
struct mount *mp;
|
|
|
|
struct vnode *vp;
|
|
|
|
struct fhandle fhp;
|
|
|
|
struct file *fp;
|
2012-07-31 18:25:00 +00:00
|
|
|
int fmode, error;
|
1999-09-11 00:46:08 +00:00
|
|
|
int indx;
|
|
|
|
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_VFS_FHOPEN);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1999-09-11 00:46:08 +00:00
|
|
|
return (error);
|
2012-06-08 18:32:09 +00:00
|
|
|
indx = -1;
|
2002-12-14 01:56:26 +00:00
|
|
|
fmode = FFLAGS(uap->flags);
|
1999-09-11 00:46:08 +00:00
|
|
|
/* why not allow a non-read/write open for our lockd? */
|
|
|
|
if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
|
|
|
|
return (EINVAL);
|
2002-12-14 01:56:26 +00:00
|
|
|
error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1999-09-11 00:46:08 +00:00
|
|
|
return(error);
|
|
|
|
/* find the mount point */
|
2008-11-29 13:34:59 +00:00
|
|
|
mp = vfs_busyfs(&fhp.fh_fsid);
|
2006-03-31 03:54:20 +00:00
|
|
|
if (mp == NULL)
|
|
|
|
return (ESTALE);
|
1999-09-11 00:46:08 +00:00
|
|
|
/* now give me my vnode, it gets returned to me locked */
|
2011-05-22 01:07:54 +00:00
|
|
|
error = VFS_FHTOVP(mp, &fhp.fh_fid, LK_EXCLUSIVE, &vp);
|
2008-11-29 13:34:59 +00:00
|
|
|
vfs_unbusy(mp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2012-06-08 18:32:09 +00:00
|
|
|
return (error);
|
2005-01-24 23:53:54 +00:00
|
|
|
|
2012-06-13 21:22:35 +00:00
|
|
|
error = falloc_noinstall(td, &fp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0) {
|
2012-06-08 18:32:09 +00:00
|
|
|
vput(vp);
|
|
|
|
return (error);
|
2012-06-13 21:22:35 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* An extra reference on `fp' has been held for us by
|
|
|
|
* falloc_noinstall().
|
|
|
|
*/
|
2012-06-13 21:32:35 +00:00
|
|
|
|
2012-06-08 18:32:09 +00:00
|
|
|
#ifdef INVARIANTS
|
|
|
|
td->td_dupfd = -1;
|
|
|
|
#endif
|
|
|
|
error = vn_open_vnode(vp, fmode, td->td_ucred, td, fp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0) {
|
2012-06-08 18:32:09 +00:00
|
|
|
KASSERT(fp->f_ops == &badfileops,
|
|
|
|
("VOP_OPEN in fhopen() set f_ops"));
|
|
|
|
KASSERT(td->td_dupfd < 0,
|
|
|
|
("fhopen() encountered fdopen()"));
|
1999-09-11 00:46:08 +00:00
|
|
|
|
2012-06-08 18:32:09 +00:00
|
|
|
vput(vp);
|
1999-09-11 00:46:08 +00:00
|
|
|
goto bad;
|
2001-10-24 18:32:17 +00:00
|
|
|
}
|
2012-06-08 18:32:09 +00:00
|
|
|
#ifdef INVARIANTS
|
|
|
|
td->td_dupfd = 0;
|
|
|
|
#endif
|
|
|
|
fp->f_vnode = vp;
|
|
|
|
fp->f_seqcount = 1;
|
2012-07-31 18:25:00 +00:00
|
|
|
finit(fp, (fmode & FMASK) | (fp->f_flag & FHASLOCK), DTYPE_VNODE, vp,
|
|
|
|
&vnops);
|
2012-06-08 18:32:09 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2013-09-05 00:19:30 +00:00
|
|
|
if ((fmode & O_TRUNC) != 0) {
|
2012-06-08 18:32:09 +00:00
|
|
|
error = fo_truncate(fp, 0, td->td_ucred, td);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2012-06-08 18:32:09 +00:00
|
|
|
goto bad;
|
|
|
|
}
|
1999-09-11 00:46:08 +00:00
|
|
|
|
Merge Capsicum overhaul:
- Capability is no longer separate descriptor type. Now every descriptor
has set of its own capability rights.
- The cap_new(2) system call is left, but it is no longer documented and
should not be used in new code.
- The new syscall cap_rights_limit(2) should be used instead of
cap_new(2), which limits capability rights of the given descriptor
without creating a new one.
- The cap_getrights(2) syscall is renamed to cap_rights_get(2).
- If CAP_IOCTL capability right is present we can further reduce allowed
ioctls list with the new cap_ioctls_limit(2) syscall. List of allowed
ioctls can be retrived with cap_ioctls_get(2) syscall.
- If CAP_FCNTL capability right is present we can further reduce fcntls
that can be used with the new cap_fcntls_limit(2) syscall and retrive
them with cap_fcntls_get(2).
- To support ioctl and fcntl white-listing the filedesc structure was
heavly modified.
- The audit subsystem, kdump and procstat tools were updated to
recognize new syscalls.
- Capability rights were revised and eventhough I tried hard to provide
backward API and ABI compatibility there are some incompatible changes
that are described in detail below:
CAP_CREATE old behaviour:
- Allow for openat(2)+O_CREAT.
- Allow for linkat(2).
- Allow for symlinkat(2).
CAP_CREATE new behaviour:
- Allow for openat(2)+O_CREAT.
Added CAP_LINKAT:
- Allow for linkat(2). ABI: Reuses CAP_RMDIR bit.
- Allow to be target for renameat(2).
Added CAP_SYMLINKAT:
- Allow for symlinkat(2).
Removed CAP_DELETE. Old behaviour:
- Allow for unlinkat(2) when removing non-directory object.
- Allow to be source for renameat(2).
Removed CAP_RMDIR. Old behaviour:
- Allow for unlinkat(2) when removing directory.
Added CAP_RENAMEAT:
- Required for source directory for the renameat(2) syscall.
Added CAP_UNLINKAT (effectively it replaces CAP_DELETE and CAP_RMDIR):
- Allow for unlinkat(2) on any object.
- Required if target of renameat(2) exists and will be removed by this
call.
Removed CAP_MAPEXEC.
CAP_MMAP old behaviour:
- Allow for mmap(2) with any combination of PROT_NONE, PROT_READ and
PROT_WRITE.
CAP_MMAP new behaviour:
- Allow for mmap(2)+PROT_NONE.
Added CAP_MMAP_R:
- Allow for mmap(PROT_READ).
Added CAP_MMAP_W:
- Allow for mmap(PROT_WRITE).
Added CAP_MMAP_X:
- Allow for mmap(PROT_EXEC).
Added CAP_MMAP_RW:
- Allow for mmap(PROT_READ | PROT_WRITE).
Added CAP_MMAP_RX:
- Allow for mmap(PROT_READ | PROT_EXEC).
Added CAP_MMAP_WX:
- Allow for mmap(PROT_WRITE | PROT_EXEC).
Added CAP_MMAP_RWX:
- Allow for mmap(PROT_READ | PROT_WRITE | PROT_EXEC).
Renamed CAP_MKDIR to CAP_MKDIRAT.
Renamed CAP_MKFIFO to CAP_MKFIFOAT.
Renamed CAP_MKNODE to CAP_MKNODEAT.
CAP_READ old behaviour:
- Allow pread(2).
- Disallow read(2), readv(2) (if there is no CAP_SEEK).
CAP_READ new behaviour:
- Allow read(2), readv(2).
- Disallow pread(2) (CAP_SEEK was also required).
CAP_WRITE old behaviour:
- Allow pwrite(2).
- Disallow write(2), writev(2) (if there is no CAP_SEEK).
CAP_WRITE new behaviour:
- Allow write(2), writev(2).
- Disallow pwrite(2) (CAP_SEEK was also required).
Added convinient defines:
#define CAP_PREAD (CAP_SEEK | CAP_READ)
#define CAP_PWRITE (CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ)
#define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE)
#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL)
#define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W)
#define CAP_MMAP_RX (CAP_MMAP_R | CAP_MMAP_X)
#define CAP_MMAP_WX (CAP_MMAP_W | CAP_MMAP_X)
#define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
#define CAP_RECV CAP_READ
#define CAP_SEND CAP_WRITE
#define CAP_SOCK_CLIENT \
(CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
#define CAP_SOCK_SERVER \
(CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \
CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \
CAP_SETSOCKOPT | CAP_SHUTDOWN)
Added defines for backward API compatibility:
#define CAP_MAPEXEC CAP_MMAP_X
#define CAP_DELETE CAP_UNLINKAT
#define CAP_MKDIR CAP_MKDIRAT
#define CAP_RMDIR CAP_UNLINKAT
#define CAP_MKFIFO CAP_MKFIFOAT
#define CAP_MKNOD CAP_MKNODAT
#define CAP_SOCK_ALL (CAP_SOCK_CLIENT | CAP_SOCK_SERVER)
Sponsored by: The FreeBSD Foundation
Reviewed by: Christoph Mallon <christoph.mallon@gmx.de>
Many aspects discussed with: rwatson, benl, jonathan
ABI compatibility discussed with: kib
2013-03-02 00:53:12 +00:00
|
|
|
error = finstall(td, fp, &indx, fmode, NULL);
|
1999-09-11 00:46:08 +00:00
|
|
|
bad:
|
2012-06-08 18:32:09 +00:00
|
|
|
fdrop(fp, td);
|
|
|
|
td->td_retval[0] = indx;
|
1999-09-11 00:46:08 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2000-09-14 19:13:59 +00:00
|
|
|
/*
|
|
|
|
* Stat an (NFS) file handle.
|
|
|
|
*/
|
1999-09-11 00:46:08 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct fhstat_args {
|
|
|
|
struct fhandle *u_fhp;
|
|
|
|
struct stat *sb;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_fhstat(struct thread *td, struct fhstat_args *uap)
|
1999-09-11 00:46:08 +00:00
|
|
|
{
|
|
|
|
struct stat sb;
|
2012-05-24 08:00:26 +00:00
|
|
|
struct fhandle fh;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = copyin(uap->u_fhp, &fh, sizeof(fh));
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
error = kern_fhstat(td, fh, &sb);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error == 0)
|
|
|
|
error = copyout(&sb, uap->sb, sizeof(sb));
|
2012-05-24 08:00:26 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_fhstat(struct thread *td, struct fhandle fh, struct stat *sb)
|
|
|
|
{
|
1999-09-11 00:46:08 +00:00
|
|
|
struct mount *mp;
|
|
|
|
struct vnode *vp;
|
|
|
|
int error;
|
|
|
|
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_VFS_FHSTAT);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1999-09-11 00:46:08 +00:00
|
|
|
return (error);
|
2008-11-29 13:34:59 +00:00
|
|
|
if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL)
|
1999-09-11 00:46:08 +00:00
|
|
|
return (ESTALE);
|
2011-05-22 01:07:54 +00:00
|
|
|
error = VFS_FHTOVP(mp, &fh.fh_fid, LK_EXCLUSIVE, &vp);
|
2008-11-29 13:34:59 +00:00
|
|
|
vfs_unbusy(mp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1999-09-11 00:46:08 +00:00
|
|
|
return (error);
|
2012-05-24 08:00:26 +00:00
|
|
|
error = vn_stat(vp, sb, td->td_ucred, NOCRED, td);
|
1999-09-11 00:46:08 +00:00
|
|
|
vput(vp);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2000-09-14 19:13:59 +00:00
|
|
|
/*
|
|
|
|
* Implement fstatfs() for (NFS) file handles.
|
|
|
|
*/
|
1999-09-11 00:46:08 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct fhstatfs_args {
|
|
|
|
struct fhandle *u_fhp;
|
|
|
|
struct statfs *buf;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-05-17 00:34:34 +00:00
|
|
|
sys_fhstatfs(struct thread *td, struct fhstatfs_args *uap)
|
2005-02-07 18:44:55 +00:00
|
|
|
{
|
2017-01-05 17:19:26 +00:00
|
|
|
struct statfs *sfp;
|
2005-02-07 18:44:55 +00:00
|
|
|
fhandle_t fh;
|
|
|
|
int error;
|
|
|
|
|
2005-05-27 19:15:46 +00:00
|
|
|
error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2005-02-07 18:44:55 +00:00
|
|
|
return (error);
|
2017-01-05 17:19:26 +00:00
|
|
|
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
|
|
|
|
error = kern_fhstatfs(td, fh, sfp);
|
|
|
|
if (error == 0)
|
|
|
|
error = copyout(sfp, uap->buf, sizeof(*sfp));
|
|
|
|
free(sfp, M_STATFS);
|
|
|
|
return (error);
|
2005-02-07 18:44:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
|
1999-09-11 00:46:08 +00:00
|
|
|
{
|
2004-06-07 12:19:55 +00:00
|
|
|
struct statfs *sp;
|
1999-09-11 00:46:08 +00:00
|
|
|
struct mount *mp;
|
|
|
|
struct vnode *vp;
|
|
|
|
int error;
|
|
|
|
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_VFS_FHSTATFS);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
1999-09-11 00:46:08 +00:00
|
|
|
return (error);
|
2008-11-29 13:34:59 +00:00
|
|
|
if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL)
|
1999-09-11 00:46:08 +00:00
|
|
|
return (ESTALE);
|
2011-05-22 01:07:54 +00:00
|
|
|
error = VFS_FHTOVP(mp, &fh.fh_fid, LK_EXCLUSIVE, &vp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0) {
|
2008-11-29 13:34:59 +00:00
|
|
|
vfs_unbusy(mp);
|
1999-09-11 00:46:08 +00:00
|
|
|
return (error);
|
2005-05-28 12:58:54 +00:00
|
|
|
}
|
2006-02-22 09:52:25 +00:00
|
|
|
vput(vp);
|
2006-03-21 23:58:37 +00:00
|
|
|
error = prison_canseemount(td->td_ucred, mp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2006-03-21 23:58:37 +00:00
|
|
|
goto out;
|
2002-07-31 01:27:33 +00:00
|
|
|
#ifdef MAC
|
2007-10-24 19:04:04 +00:00
|
|
|
error = mac_mount_check_stat(td->td_ucred, mp);
|
2013-09-05 00:19:30 +00:00
|
|
|
if (error != 0)
|
2006-03-21 23:58:37 +00:00
|
|
|
goto out;
|
2002-07-31 01:27:33 +00:00
|
|
|
#endif
|
2003-11-12 08:01:40 +00:00
|
|
|
/*
|
|
|
|
* Set these in case the underlying filesystem fails to do so.
|
|
|
|
*/
|
2006-02-23 05:18:07 +00:00
|
|
|
sp = &mp->mnt_stat;
|
2003-11-12 08:01:40 +00:00
|
|
|
sp->f_version = STATFS_VERSION;
|
|
|
|
sp->f_namemax = NAME_MAX;
|
|
|
|
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
|
2009-05-11 15:33:26 +00:00
|
|
|
error = VFS_STATFS(mp, sp);
|
2006-09-20 00:32:07 +00:00
|
|
|
if (error == 0)
|
|
|
|
*buf = *sp;
|
2006-03-21 23:58:37 +00:00
|
|
|
out:
|
2008-11-29 13:34:59 +00:00
|
|
|
vfs_unbusy(mp);
|
2006-03-21 23:58:37 +00:00
|
|
|
return (error);
|
1999-09-11 00:46:08 +00:00
|
|
|
}
|
2011-04-18 16:32:22 +00:00
|
|
|
|
2011-11-14 18:00:15 +00:00
|
|
|
int
|
2011-04-18 16:32:22 +00:00
|
|
|
kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len)
|
|
|
|
{
|
|
|
|
struct file *fp;
|
|
|
|
struct mount *mp;
|
|
|
|
struct vnode *vp;
|
2011-04-19 16:36:24 +00:00
|
|
|
off_t olen, ooffset;
|
2012-10-22 21:14:26 +00:00
|
|
|
int error;
|
2017-03-31 14:17:14 +00:00
|
|
|
#ifdef AUDIT
|
|
|
|
int audited_vnode1 = 0;
|
|
|
|
#endif
|
2011-04-18 16:32:22 +00:00
|
|
|
|
2017-03-31 14:17:14 +00:00
|
|
|
AUDIT_ARG_FD(fd);
|
2014-11-12 17:31:38 +00:00
|
|
|
if (offset < 0 || len <= 0)
|
|
|
|
return (EINVAL);
|
|
|
|
/* Check for wrap. */
|
|
|
|
if (offset > OFF_MAX - len)
|
|
|
|
return (EFBIG);
|
2017-03-31 14:17:14 +00:00
|
|
|
AUDIT_ARG_FD(fd);
|
2018-05-09 18:47:24 +00:00
|
|
|
error = fget(td, fd, &cap_pwrite_rights, &fp);
|
2011-04-18 16:32:22 +00:00
|
|
|
if (error != 0)
|
2014-11-12 17:31:38 +00:00
|
|
|
return (error);
|
2017-03-31 14:17:14 +00:00
|
|
|
AUDIT_ARG_FILE(td->td_proc, fp);
|
2014-11-12 17:31:38 +00:00
|
|
|
if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE) == 0) {
|
2011-04-18 16:32:22 +00:00
|
|
|
error = ESPIPE;
|
|
|
|
goto out;
|
|
|
|
}
|
2011-04-18 16:40:47 +00:00
|
|
|
if ((fp->f_flag & FWRITE) == 0) {
|
|
|
|
error = EBADF;
|
2011-04-18 16:32:22 +00:00
|
|
|
goto out;
|
2011-04-18 16:40:47 +00:00
|
|
|
}
|
2014-11-12 17:31:38 +00:00
|
|
|
if (fp->f_type != DTYPE_VNODE) {
|
2011-04-18 16:32:22 +00:00
|
|
|
error = ENODEV;
|
|
|
|
goto out;
|
|
|
|
}
|
2014-11-12 17:31:38 +00:00
|
|
|
vp = fp->f_vnode;
|
|
|
|
if (vp->v_type != VREG) {
|
|
|
|
error = ENODEV;
|
2011-04-18 16:32:22 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2011-04-19 16:36:24 +00:00
|
|
|
/* Allocating blocks may take a long time, so iterate. */
|
|
|
|
for (;;) {
|
|
|
|
olen = len;
|
|
|
|
ooffset = offset;
|
|
|
|
|
|
|
|
bwillwrite();
|
|
|
|
mp = NULL;
|
|
|
|
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
|
2012-10-22 17:50:54 +00:00
|
|
|
if (error != 0)
|
2011-04-19 16:36:24 +00:00
|
|
|
break;
|
|
|
|
error = vn_lock(vp, LK_EXCLUSIVE);
|
|
|
|
if (error != 0) {
|
|
|
|
vn_finished_write(mp);
|
|
|
|
break;
|
|
|
|
}
|
2017-03-31 14:17:14 +00:00
|
|
|
#ifdef AUDIT
|
|
|
|
if (!audited_vnode1) {
|
|
|
|
AUDIT_ARG_VNODE1(vp);
|
|
|
|
audited_vnode1 = 1;
|
|
|
|
}
|
|
|
|
#endif
|
2011-04-18 16:32:22 +00:00
|
|
|
#ifdef MAC
|
2011-04-19 16:36:24 +00:00
|
|
|
error = mac_vnode_check_write(td->td_ucred, fp->f_cred, vp);
|
|
|
|
if (error == 0)
|
2011-04-18 16:32:22 +00:00
|
|
|
#endif
|
2011-04-19 16:36:24 +00:00
|
|
|
error = VOP_ALLOCATE(vp, &offset, &len);
|
2011-04-18 16:32:22 +00:00
|
|
|
VOP_UNLOCK(vp, 0);
|
2011-04-19 16:36:24 +00:00
|
|
|
vn_finished_write(mp);
|
|
|
|
|
|
|
|
if (olen + ooffset != offset + len) {
|
|
|
|
panic("offset + len changed from %jx/%jx to %jx/%jx",
|
|
|
|
ooffset, olen, offset, len);
|
|
|
|
}
|
|
|
|
if (error != 0 || len == 0)
|
|
|
|
break;
|
|
|
|
KASSERT(olen > len, ("Iteration did not make progress?"));
|
|
|
|
maybe_yield();
|
|
|
|
}
|
|
|
|
out:
|
2014-11-12 17:31:38 +00:00
|
|
|
fdrop(fp, td);
|
2011-04-18 16:32:22 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_posix_fallocate(struct thread *td, struct posix_fallocate_args *uap)
|
2011-04-18 16:32:22 +00:00
|
|
|
{
|
2016-02-25 19:58:23 +00:00
|
|
|
int error;
|
2011-04-18 16:32:22 +00:00
|
|
|
|
2016-02-25 19:58:23 +00:00
|
|
|
error = kern_posix_fallocate(td, uap->fd, uap->offset, uap->len);
|
|
|
|
return (kern_posix_error(td, error));
|
2011-04-18 16:32:22 +00:00
|
|
|
}
|
2011-11-04 04:02:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Unlike madvise(2), we do not make a best effort to remember every
|
|
|
|
* possible caching hint. Instead, we remember the last setting with
|
|
|
|
* the exception that we will allow POSIX_FADV_NORMAL to adjust the
|
|
|
|
* region of any current setting.
|
|
|
|
*/
|
|
|
|
int
|
2011-11-14 18:00:15 +00:00
|
|
|
kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len,
|
|
|
|
int advice)
|
2011-11-04 04:02:50 +00:00
|
|
|
{
|
|
|
|
struct fadvise_info *fa, *new;
|
|
|
|
struct file *fp;
|
|
|
|
struct vnode *vp;
|
|
|
|
off_t end;
|
|
|
|
int error;
|
|
|
|
|
2011-11-14 18:00:15 +00:00
|
|
|
if (offset < 0 || len < 0 || offset > OFF_MAX - len)
|
2011-11-04 04:02:50 +00:00
|
|
|
return (EINVAL);
|
2017-03-31 14:17:14 +00:00
|
|
|
AUDIT_ARG_VALUE(advice);
|
2011-11-14 18:00:15 +00:00
|
|
|
switch (advice) {
|
2011-11-04 04:02:50 +00:00
|
|
|
case POSIX_FADV_SEQUENTIAL:
|
|
|
|
case POSIX_FADV_RANDOM:
|
|
|
|
case POSIX_FADV_NOREUSE:
|
|
|
|
new = malloc(sizeof(*fa), M_FADVISE, M_WAITOK);
|
|
|
|
break;
|
|
|
|
case POSIX_FADV_NORMAL:
|
|
|
|
case POSIX_FADV_WILLNEED:
|
|
|
|
case POSIX_FADV_DONTNEED:
|
|
|
|
new = NULL;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
/* XXX: CAP_POSIX_FADVISE? */
|
2017-03-31 14:17:14 +00:00
|
|
|
AUDIT_ARG_FD(fd);
|
2018-05-09 18:47:24 +00:00
|
|
|
error = fget(td, fd, &cap_no_rights, &fp);
|
2011-11-04 04:02:50 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto out;
|
2017-03-31 14:17:14 +00:00
|
|
|
AUDIT_ARG_FILE(td->td_proc, fp);
|
2014-11-12 17:31:38 +00:00
|
|
|
if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE) == 0) {
|
2011-11-04 04:02:50 +00:00
|
|
|
error = ESPIPE;
|
|
|
|
goto out;
|
2014-11-12 17:31:38 +00:00
|
|
|
}
|
|
|
|
if (fp->f_type != DTYPE_VNODE) {
|
2011-11-04 04:02:50 +00:00
|
|
|
error = ENODEV;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
vp = fp->f_vnode;
|
|
|
|
if (vp->v_type != VREG) {
|
|
|
|
error = ENODEV;
|
|
|
|
goto out;
|
|
|
|
}
|
2011-11-14 18:00:15 +00:00
|
|
|
if (len == 0)
|
2011-11-04 04:02:50 +00:00
|
|
|
end = OFF_MAX;
|
|
|
|
else
|
2011-11-14 18:00:15 +00:00
|
|
|
end = offset + len - 1;
|
|
|
|
switch (advice) {
|
2011-11-04 04:02:50 +00:00
|
|
|
case POSIX_FADV_SEQUENTIAL:
|
|
|
|
case POSIX_FADV_RANDOM:
|
|
|
|
case POSIX_FADV_NOREUSE:
|
|
|
|
/*
|
|
|
|
* Try to merge any existing non-standard region with
|
|
|
|
* this new region if possible, otherwise create a new
|
|
|
|
* non-standard region for this request.
|
|
|
|
*/
|
|
|
|
mtx_pool_lock(mtxpool_sleep, fp);
|
|
|
|
fa = fp->f_advice;
|
2011-11-14 18:00:15 +00:00
|
|
|
if (fa != NULL && fa->fa_advice == advice &&
|
|
|
|
((fa->fa_start <= end && fa->fa_end >= offset) ||
|
2011-11-04 04:02:50 +00:00
|
|
|
(end != OFF_MAX && fa->fa_start == end + 1) ||
|
2011-11-14 18:00:15 +00:00
|
|
|
(fa->fa_end != OFF_MAX && fa->fa_end + 1 == offset))) {
|
|
|
|
if (offset < fa->fa_start)
|
|
|
|
fa->fa_start = offset;
|
2011-11-04 04:02:50 +00:00
|
|
|
if (end > fa->fa_end)
|
|
|
|
fa->fa_end = end;
|
|
|
|
} else {
|
2011-11-14 18:00:15 +00:00
|
|
|
new->fa_advice = advice;
|
|
|
|
new->fa_start = offset;
|
2011-11-04 04:02:50 +00:00
|
|
|
new->fa_end = end;
|
|
|
|
fp->f_advice = new;
|
|
|
|
new = fa;
|
|
|
|
}
|
|
|
|
mtx_pool_unlock(mtxpool_sleep, fp);
|
|
|
|
break;
|
|
|
|
case POSIX_FADV_NORMAL:
|
|
|
|
/*
|
|
|
|
* If a the "normal" region overlaps with an existing
|
|
|
|
* non-standard region, trim or remove the
|
|
|
|
* non-standard region.
|
|
|
|
*/
|
|
|
|
mtx_pool_lock(mtxpool_sleep, fp);
|
|
|
|
fa = fp->f_advice;
|
|
|
|
if (fa != NULL) {
|
2011-11-14 18:00:15 +00:00
|
|
|
if (offset <= fa->fa_start && end >= fa->fa_end) {
|
2011-11-04 04:02:50 +00:00
|
|
|
new = fa;
|
|
|
|
fp->f_advice = NULL;
|
2011-11-14 18:00:15 +00:00
|
|
|
} else if (offset <= fa->fa_start &&
|
2013-03-16 22:37:30 +00:00
|
|
|
end >= fa->fa_start)
|
2011-11-04 04:02:50 +00:00
|
|
|
fa->fa_start = end + 1;
|
2011-11-14 18:00:15 +00:00
|
|
|
else if (offset <= fa->fa_end && end >= fa->fa_end)
|
|
|
|
fa->fa_end = offset - 1;
|
|
|
|
else if (offset >= fa->fa_start && end <= fa->fa_end) {
|
2011-11-04 04:02:50 +00:00
|
|
|
/*
|
|
|
|
* If the "normal" region is a middle
|
|
|
|
* portion of the existing
|
|
|
|
* non-standard region, just remove
|
|
|
|
* the whole thing rather than picking
|
|
|
|
* one side or the other to
|
|
|
|
* preserve.
|
|
|
|
*/
|
|
|
|
new = fa;
|
|
|
|
fp->f_advice = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mtx_pool_unlock(mtxpool_sleep, fp);
|
|
|
|
break;
|
|
|
|
case POSIX_FADV_WILLNEED:
|
|
|
|
case POSIX_FADV_DONTNEED:
|
2011-11-14 18:00:15 +00:00
|
|
|
error = VOP_ADVISE(vp, offset, end, advice);
|
2011-11-04 04:02:50 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
if (fp != NULL)
|
|
|
|
fdrop(fp, td);
|
|
|
|
free(new, M_FADVISE);
|
|
|
|
return (error);
|
|
|
|
}
|
2011-11-14 18:00:15 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
sys_posix_fadvise(struct thread *td, struct posix_fadvise_args *uap)
|
|
|
|
{
|
2016-02-25 19:58:23 +00:00
|
|
|
int error;
|
2011-11-14 18:00:15 +00:00
|
|
|
|
2016-02-25 19:58:23 +00:00
|
|
|
error = kern_posix_fadvise(td, uap->fd, uap->offset, uap->len,
|
|
|
|
uap->advice);
|
|
|
|
return (kern_posix_error(td, error));
|
2011-11-14 18:00:15 +00:00
|
|
|
}
|