Page MenuHomeFreeBSD

D21391.id61234.diff
No OneTemporary

D21391.id61234.diff

Index: lib/libc/sys/fcntl.2
===================================================================
--- lib/libc/sys/fcntl.2
+++ lib/libc/sys/fcntl.2
@@ -28,7 +28,7 @@
.\" @(#)fcntl.2 8.2 (Berkeley) 1/12/94
.\" $FreeBSD$
.\"
-.Dd Nov 15, 2018
+.Dd August 24, 2019
.Dt FCNTL 2
.Os
.Sh NAME
@@ -180,6 +180,13 @@
A zero value in
.Fa arg
turns off read ahead.
+.It Dv F_ADD_SEALS
+Add seals to the file as described below, if the underlying filesystem supports
+seals.
+.It Dv F_GET_SEALS
+Get seals associated with descriptor
+.Fa fd ,
+if the underlying filesystem supports seals.
.El
.Pp
The flags for the
@@ -217,6 +224,32 @@
upon availability of data to be read.
.El
.Pp
+The seals that may be applied with
+.Dv F_ADD_SEALS
+are as follows:
+.Bl -tag -width F_SEAL_SHRINK
+.It Dv F_SEAL_SEAL
+Prevent any further seals from being applied to the file.
+.It Dv F_SEAL_SHRINK
+Prevent the file from being shrunk with
+.Xr ftruncate 2 .
+.It Dv F_SEAL_GROW
+Prevent the file from being enlarged with
+.Xr ftruncate 2 .
+.It Dv F_SEAL_WRITE
+Prevent any further
+.Xr write 2
+calls to the file.
+.El
+.Pp
+Seals are on a per-inode basis and require support by the underlying filesystem.
+If the underlying filesystem does not support seals,
+.Dv F_ADD_SEALS
+and
+.Dv F_GET_SEALS
+will error out with
+.Dv EINVAL .
+.Pp
Several commands are available for doing advisory file locking;
they all operate on the following structure:
.Bd -literal
@@ -565,6 +598,14 @@
.Pp
The argument
.Fa cmd
+is
+.Dv F_ADD_SEALS
+or
+.Dv F_GET_SEALS ,
+and the underlying filesystem does not support sealing.
+.Pp
+The argument
+.Fa cmd
is invalid.
.It Bq Er EMFILE
The argument
Index: lib/libc/sys/truncate.2
===================================================================
--- lib/libc/sys/truncate.2
+++ lib/libc/sys/truncate.2
@@ -28,7 +28,7 @@
.\" @(#)truncate.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd May 4, 2015
+.Dd August 24, 2019
.Dt TRUNCATE 2
.Os
.Sh NAME
@@ -144,6 +144,8 @@
.Fa fd
descriptor
is not open for writing.
+.It Bq Er ENOTCAPABLE
+The file descriptor being operated on has insufficient rights.
.El
.Sh SEE ALSO
.Xr chflags 2 ,
Index: sys/kern/kern_descrip.c
===================================================================
--- sys/kern/kern_descrip.c
+++ sys/kern/kern_descrip.c
@@ -46,6 +46,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/caprights.h>
#include <sys/capsicum.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
@@ -483,13 +484,14 @@
int
kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
{
+ cap_rights_t rights;
struct filedesc *fdp;
struct flock *flp;
struct file *fp, *fp2;
struct filedescent *fde;
struct proc *p;
struct vnode *vp;
- int error, flg, tmp;
+ int error, flg, seals, tmp;
uint64_t bsize;
off_t foffset;
@@ -756,6 +758,58 @@
fdrop(fp, td);
break;
+ case F_ADD_SEALS:
+ error = fget_unlocked(fdp, fd, &cap_no_rights, &fp, NULL);
+ if (error != 0)
+ break;
+ if ((fp->f_flag & (FWRITE | FSEALABLE)) != (FWRITE | FSEALABLE))
+ error = EINVAL;
+ else if (fo_get_seals(fp, &seals) != 0)
+ error = EINVAL;
+ else if ((seals & F_SEAL_SEAL) != 0)
+ error = EPERM;
+ if (error != 0) {
+ fdrop(fp, td);
+ break;
+ }
+
+ tmp = (arg & ~seals);
+ /* Nop; the rest isn't worth evaluating */
+ if (tmp == 0) {
+ fdrop(fp, td);
+ break;
+ }
+
+ /* This shouldn't fail; if it does, we can't act on this seal */
+ error = fo_add_seals(fp, arg);
+ if (error != 0) {
+ fdrop(fp, td);
+ break;
+ }
+
+ /* F_SEAL_WRITE translates to revoking CAP_WRITE */
+ if ((tmp & F_SEAL_WRITE) != 0) {
+ rights = *cap_rights(fdp, fd);
+ cap_rights_clear(&rights, CAP_WRITE);
+
+ kern_cap_rights_limit(td, fd, &rights);
+ }
+
+ fdrop(fp, td);
+ break;
+
+ case F_GET_SEALS:
+ error = fget_unlocked(fdp, fd, &cap_no_rights, &fp, NULL);
+ if (error != 0)
+ break;
+ if ((fp->f_flag & FSEALABLE) != 0 &&
+ fo_get_seals(fp, &seals) == 0)
+ td->td_retval[0] = seals;
+ else
+ error = EINVAL;
+ fdrop(fp, td);
+ break;
+
case F_RDAHEAD:
arg = arg ? 128 * 1024: 0;
/* FALLTHROUGH */
Index: sys/kern/sys_generic.c
===================================================================
--- sys/kern/sys_generic.c
+++ sys/kern/sys_generic.c
@@ -63,6 +63,7 @@
#include <sys/resourcevar.h>
#include <sys/selinfo.h>
#include <sys/sleepqueue.h>
+#include <sys/stat.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
@@ -595,8 +596,9 @@
int
kern_ftruncate(struct thread *td, int fd, off_t length)
{
+ struct stat sb;
struct file *fp;
- int error;
+ int error, seals;
AUDIT_ARG_FD(fd);
if (length < 0)
@@ -606,10 +608,30 @@
return (error);
AUDIT_ARG_FILE(td->td_proc, fp);
if (!(fp->f_flag & FWRITE)) {
- fdrop(fp, td);
- return (EINVAL);
+ error = EINVAL;
+ goto out;
+ }
+ if (fo_get_seals(fp, &seals) == 0 && (seals & F_SEAL_TRUNCATE) != 0) {
+ error = fo_stat(fp, &sb, td->td_ucred, td);
+ /*
+ * F_SEAL_SHRINK | F_SEAL_GROW still allows a call to ftruncate
+ * with no shrink or growth. If this were not the case, we
+ * would instead just revoke CAP_FTRUNCATE.
+ */
+ if (error == 0 && length != sb.st_size) {
+ if (length < sb.st_size &&
+ (seals & F_SEAL_SHRINK) != 0) {
+ error = ENOTCAPABLE;
+ goto out;
+ } else if (length > sb.st_size &&
+ (seals & F_SEAL_GROW) != 0) {
+ error = ENOTCAPABLE;
+ goto out;
+ }
+ }
}
error = fo_truncate(fp, length, td->td_ucred, td);
+out:
fdrop(fp, td);
return (error);
}
Index: sys/kern/uipc_shm.c
===================================================================
--- sys/kern/uipc_shm.c
+++ sys/kern/uipc_shm.c
@@ -131,6 +131,8 @@
static fo_seek_t shm_seek;
static fo_fill_kinfo_t shm_fill_kinfo;
static fo_mmap_t shm_mmap;
+static fo_get_seals_t shm_get_seals;
+static fo_add_seals_t shm_add_seals;
/* File descriptor operations. */
struct fileops shm_ops = {
@@ -148,6 +150,8 @@
.fo_seek = shm_seek,
.fo_fill_kinfo = shm_fill_kinfo,
.fo_mmap = shm_mmap,
+ .fo_get_seals = shm_get_seals,
+ .fo_add_seals = shm_add_seals,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
@@ -1143,6 +1147,26 @@
return (res);
}
+static int
+shm_add_seals(struct file *fp, int seals)
+{
+ struct shmfd *shmfd;
+
+ shmfd = fp->f_data;
+ atomic_set_int(&shmfd->shm_seals, seals);
+ return (0);
+}
+
+static int
+shm_get_seals(struct file *fp, int *seals)
+{
+ struct shmfd *shmfd;
+
+ shmfd = fp->f_data;
+ *seals = shmfd->shm_seals;
+ return (0);
+}
+
static int
sysctl_posix_shm_list(SYSCTL_HANDLER_ARGS)
{
Index: sys/sys/fcntl.h
===================================================================
--- sys/sys/fcntl.h
+++ sys/sys/fcntl.h
@@ -196,6 +196,10 @@
#define FRDAHEAD O_CREAT
#endif
+#ifdef _KERNEL
+#define FSEALABLE O_TRUNC
+#endif
+
#if __POSIX_VISIBLE >= 200809
/*
* Magic value that specify the use of the current working directory
@@ -248,8 +252,22 @@
#endif
#if __BSD_VISIBLE
#define F_DUP2FD_CLOEXEC 18 /* Like F_DUP2FD, but FD_CLOEXEC is set */
+#define F_ADD_SEALS 19
+#define F_GET_SEALS 20
#endif
+/* Seals (F_ADD_SEALS, F_GET_SEALS */
+#if __BSD_VISIBLE
+#define F_SEAL_SEAL 0x0001 /* Prevent adding sealings */
+#define F_SEAL_SHRINK 0x0002 /* May not shrink */
+#define F_SEAL_GROW 0x0004 /* May not grow */
+#define F_SEAL_WRITE 0x0008 /* May not write */
+
+#ifdef _KERNEL
+#define F_SEAL_TRUNCATE (F_SEAL_SHRINK | F_SEAL_GROW)
+#endif /* _KERNEL */
+#endif /* __BSD_VISIBLE */
+
/* file descriptor flags (F_GETFD, F_SETFD) */
#define FD_CLOEXEC 1 /* close-on-exec flag */
Index: sys/sys/file.h
===================================================================
--- sys/sys/file.h
+++ sys/sys/file.h
@@ -123,6 +123,8 @@
vm_size_t size, vm_prot_t prot, vm_prot_t cap_maxprot,
int flags, vm_ooffset_t foff, struct thread *td);
typedef int fo_aio_queue_t(struct file *fp, struct kaiocb *job);
+typedef int fo_add_seals_t(struct file *fp, int flags);
+typedef int fo_get_seals_t(struct file *fp, int *flags);
typedef int fo_flags_t;
struct fileops {
@@ -141,6 +143,8 @@
fo_fill_kinfo_t *fo_fill_kinfo;
fo_mmap_t *fo_mmap;
fo_aio_queue_t *fo_aio_queue;
+ fo_add_seals_t *fo_add_seals;
+ fo_get_seals_t *fo_get_seals;
fo_flags_t fo_flags; /* DFLAG_* below */
};
@@ -426,6 +430,26 @@
return ((*fp->f_ops->fo_aio_queue)(fp, job));
}
+static __inline int
+fo_add_seals(struct file *fp, int seals)
+{
+
+ if (fp->f_ops->fo_add_seals == NULL)
+ return (ENODEV);
+ return ((*fp->f_ops->fo_add_seals)(fp, seals));
+}
+
+static __inline int
+fo_get_seals(struct file *fp, int *seals)
+{
+
+ if (fp->f_ops->fo_get_seals == NULL)
+ return (ENODEV);
+ if (seals == NULL)
+ return (EINVAL);
+ return ((*fp->f_ops->fo_get_seals)(fp, seals));
+}
+
#endif /* _KERNEL */
#endif /* !SYS_FILE_H */
Index: sys/sys/mman.h
===================================================================
--- sys/sys/mman.h
+++ sys/sys/mman.h
@@ -238,6 +238,8 @@
struct rangelock shm_rl;
struct mtx shm_mtx;
+
+ int shm_seals;
};
#endif

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 1, 6:48 AM (12 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28301109
Default Alt Text
D21391.id61234.diff (8 KB)

Event Timeline