Page MenuHomeFreeBSD

D21391.1779193573.diff
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None

D21391.1779193573.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 descriptor
+.Fa fd ,
+as described below.
+.It Dv F_GET_SEALS
+Get seals associated with descriptor
+.Fa fd .
.El
.Pp
The flags for the
@@ -217,6 +224,30 @@
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
+.Fa fd .
+.It Dv F_SEAL_SHRINK
+Prevent
+.Fa fd
+from being shrunk with
+.Xr ftruncate 2 .
+.It Dv F_SEAL_GROW
+Prevent
+.Fa fd
+from being enlarged with
+.Xr ftruncate 2 .
+.It Dv F_SEAL_WRITE
+Prevent any further
+.Xr write 2
+calls to
+.Fa fd .
+.El
+.Pp
Several commands are available for doing advisory file locking;
they all operate on the following structure:
.Bd -literal
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,6 +484,7 @@
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;
@@ -492,6 +494,7 @@
int error, flg, tmp;
uint64_t bsize;
off_t foffset;
+ bool setcaps;
error = 0;
flg = F_POSIX;
@@ -756,6 +759,61 @@
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 ((fp->f_seals & F_SEAL_SEAL) != 0)
+ error = EPERM;
+ if (error != 0) {
+ fdrop(fp, td);
+ break;
+ }
+
+ tmp = (arg & ~fp->f_seals);
+ /* No new bits? break out, no harm no foul. */
+ if (tmp == 0) {
+ fdrop(fp, td);
+ break;
+ }
+
+ /* fp->f_seals can never be cleared */
+ atomic_set_int(&fp->f_seals, arg);
+ rights = *cap_rights(fdp, fd);
+ setcaps = false;
+
+ /* F_SEAL_WRITE translates to revoking CAP_WRITE */
+ if ((tmp & F_SEAL_WRITE) != 0) {
+ cap_rights_clear(&rights, CAP_WRITE);
+ setcaps = true;
+ }
+
+ /* We can revoke truncate completely */
+ if ((tmp & F_SEAL_TRUNCATE) != 0 &&
+ (fp->f_seals & F_SEAL_TRUNCATE) == F_SEAL_TRUNCATE) {
+ cap_rights_clear(&rights, CAP_FTRUNCATE);
+ setcaps = true;
+ }
+
+ if (setcaps)
+ 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)
+ error = EINVAL;
+ else
+ td->td_retval[0] = fp->f_seals;
+ 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,6 +596,7 @@
int
kern_ftruncate(struct thread *td, int fd, off_t length)
{
+ struct stat sb;
struct file *fp;
int error;
@@ -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;
+ }
+ /*
+ * ftruncate being completely sealed is already handled by revoking the
+ * ftruncate capability completely. Here we only have to handle the
+ * case of either restricted shrink or restricted growth, but not both.
+ */
+ if ((fp->f_seals & F_SEAL_TRUNCATE) != 0) {
+ error = fo_stat(fp, &sb, td->td_ucred, td);
+ if (error == 0) {
+ if (length < sb.st_size &&
+ (fp->f_seals & F_SEAL_SHRINK) != 0) {
+ error = ENOTCAPABLE;
+ goto out;
+ } else if (length > sb.st_size &&
+ (fp->f_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/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
@@ -197,6 +197,10 @@
* Mandatory Access control information.
*/
void *f_label; /* Place-holder for MAC label. */
+ /*
+ * Current seals on the fd
+ */
+ uint32_t f_seals;
};
#define f_cdevpriv f_vnun.fvn_cdevpriv
Index: sys/sys/param.h
===================================================================
--- sys/sys/param.h
+++ sys/sys/param.h
@@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1300040 /* Master, propagated to newvers */
+#define __FreeBSD_version 1300041 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

File Metadata

Mime Type
text/plain
Expires
Tue, May 19, 12:26 PM (5 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28745080
Default Alt Text
D21391.1779193573.diff (6 KB)

Event Timeline