summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/openbsm/etc/audit_event1
-rw-r--r--lib/libc/sys/Symbol.map1
-rw-r--r--sys/bsm/audit_kevents.h1
-rw-r--r--sys/compat/freebsd32/syscalls.master2
-rw-r--r--sys/kern/capabilities.conf1
-rw-r--r--sys/kern/syscalls.master2
-rw-r--r--sys/kern/vfs_syscalls.c65
-rw-r--r--sys/sys/capability.h1
-rw-r--r--sys/sys/stat.h1
9 files changed, 60 insertions, 15 deletions
diff --git a/contrib/openbsm/etc/audit_event b/contrib/openbsm/etc/audit_event
index 49b5f9d..b4596b0 100644
--- a/contrib/openbsm/etc/audit_event
+++ b/contrib/openbsm/etc/audit_event
@@ -570,6 +570,7 @@
43206:AUE_CAP_FCNTLS_GET:cap_fcntls_get(2):fm
43207:AUE_BINDAT:bindat(2):nt
43208:AUE_CONNECTAT:connectat(2):nt
+43209:AUE_CHFLAGSAT:chflagsat(2):fm
#
# Solaris userspace events.
#
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
index fc00064..6faa0af 100644
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -386,6 +386,7 @@ FBSD_1.3 {
cap_rights_get;
cap_rights_limit;
cap_sandboxed;
+ chflagsat;
clock_getcpuclockid2;
connectat;
ffclock_getcounter;
diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h
index d56a96b..da2bc7c 100644
--- a/sys/bsm/audit_kevents.h
+++ b/sys/bsm/audit_kevents.h
@@ -610,6 +610,7 @@
#define AUE_CAP_FCNTLS_GET 43206 /* TrustedBSD. */
#define AUE_BINDAT 43207 /* TrustedBSD. */
#define AUE_CONNECTAT 43208 /* TrustedBSD. */
+#define AUE_CHFLAGSAT 43209 /* FreeBSD-specific. */
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index e7a18aa..b798d8c 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -1020,3 +1020,5 @@
int namelen); }
539 AUE_CONNECTAT NOPROTO { int connectat(int fd, int s, caddr_t name, \
int namelen); }
+540 AUE_CHFLAGSAT NOPROTO { int chflagsat(int fd, const char *path, \
+ u_long flags, int atflag); }
diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf
index be01c9d..f54c25d 100644
--- a/sys/kern/capabilities.conf
+++ b/sys/kern/capabilities.conf
@@ -445,6 +445,7 @@ olio_listio
##
## Operations relative to directory capabilities.
##
+chflagsat
faccessat
fchmodat
fchownat
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 7b45c80..cf4138a 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -970,5 +970,7 @@
int namelen); }
539 AUE_CONNECTAT STD { int connectat(int fd, int s, caddr_t name, \
int namelen); }
+540 AUE_CHFLAGSAT STD { int chflagsat(int fd, const char *path, \
+ u_long flags, int atflag); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 6195321..10e9c99 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -101,6 +101,10 @@ SDT_PROBE_ARGTYPE(vfs, , stat, reg, 1, "int");
static int chroot_refuse_vdir_fds(struct filedesc *fdp);
static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
+static int kern_chflags(struct thread *td, const char *path,
+ enum uio_seg pathseg, u_long flags);
+static int kern_chflagsat(struct thread *td, int fd, const char *path,
+ enum uio_seg pathseg, u_long flags, int atflag);
static int setfflags(struct thread *td, struct vnode *, u_long);
static int setutimes(struct thread *td, struct vnode *,
const struct timespec *, int, int);
@@ -2669,17 +2673,38 @@ sys_chflags(td, uap)
u_long flags;
} */ *uap;
{
- int error;
- struct nameidata nd;
- AUDIT_ARG_FFLAGS(uap->flags);
- NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td);
- if ((error = namei(&nd)) != 0)
- return (error);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- error = setfflags(td, nd.ni_vp, uap->flags);
- vrele(nd.ni_vp);
- return (error);
+ return (kern_chflags(td, uap->path, UIO_USERSPACE, uap->flags));
+}
+
+#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)
+{
+ int fd = uap->fd;
+ char *path = uap->path;
+ u_long flags = uap->flags;
+ int atflag = uap->atflag;
+
+ if (atflag & ~AT_SYMLINK_NOFOLLOW)
+ return (EINVAL);
+
+ return (kern_chflagsat(td, fd, path, UIO_USERSPACE, flags, atflag));
+}
+
+static int
+kern_chflags(struct thread *td, const char *path, enum uio_seg pathseg,
+ u_long flags)
+{
+
+ return (kern_chflagsat(td, AT_FDCWD, path, pathseg, flags, 0));
}
/*
@@ -2693,16 +2718,26 @@ sys_lchflags(td, uap)
u_long flags;
} */ *uap;
{
- int error;
+
+ 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)
+{
struct nameidata nd;
+ int error, follow;
- AUDIT_ARG_FFLAGS(uap->flags);
- NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path,
- td);
+ AUDIT_ARG_FFLAGS(flags);
+ follow = (atflag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
+ NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
+ CAP_FCHFLAGS, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = setfflags(td, nd.ni_vp, uap->flags);
+ error = setfflags(td, nd.ni_vp, flags);
vrele(nd.ni_vp);
return (error);
}
diff --git a/sys/sys/capability.h b/sys/sys/capability.h
index 0d1ea5c..ec63de7 100644
--- a/sys/sys/capability.h
+++ b/sys/sys/capability.h
@@ -102,6 +102,7 @@
/* VFS methods. */
#define CAP_FCHDIR 0x0000000000000200ULL
#define CAP_FCHFLAGS 0x0000000000000100ULL
+#define CAP_CHFLAGSAT CAP_FCHFLAGS
#define CAP_FCHMOD 0x0000000000000400ULL
#define CAP_FCHMODAT CAP_FCHMOD
#define CAP_FCHOWN 0x0000000000000800ULL
diff --git a/sys/sys/stat.h b/sys/sys/stat.h
index ec6efae..f430a9a 100644
--- a/sys/sys/stat.h
+++ b/sys/sys/stat.h
@@ -293,6 +293,7 @@ struct nstat {
__BEGIN_DECLS
#if __BSD_VISIBLE
int chflags(const char *, unsigned long);
+int chflagsat(int, const char *, unsigned long, int);
#endif
int chmod(const char *, mode_t);
#if __BSD_VISIBLE
OpenPOWER on IntegriCloud