Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143688200
D21391.id61234.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D21391.id61234.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D21391: [1/3] Add mostly Linux-compatible file sealing support
Attached
Detach File
Event Timeline
Log In to Comment