@@ -34,6 +34,7 @@
#define O_PATH 040000000
#define __O_TMPFILE 0100000000
+#define O_ALLOW_ENCODED 0200000000
#define F_GETLK 7
#define F_SETLK 8
@@ -22,6 +22,7 @@
#define O_PATH 020000000
#define __O_TMPFILE 040000000
+#define O_ALLOW_ENCODED 100000000
#define F_GETLK64 8
#define F_SETLK64 9
@@ -37,6 +37,7 @@
#define O_PATH 0x1000000
#define __O_TMPFILE 0x2000000
+#define O_ALLOW_ENCODED 0x8000000
#define F_GETOWN 5 /* for sockets. */
#define F_SETOWN 6 /* for sockets. */
@@ -30,7 +30,8 @@
#include <asm/siginfo.h>
#include <linux/uaccess.h>
-#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
+#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME | \
+ O_ALLOW_ENCODED)
static int setfl(int fd, struct file * filp, unsigned long arg)
{
@@ -49,6 +50,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
if (!inode_owner_or_capable(inode))
return -EPERM;
+ /* O_ALLOW_ENCODED can only be set by superuser */
+ if ((arg & O_ALLOW_ENCODED) && !(filp->f_flags & O_ALLOW_ENCODED) &&
+ !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
/* required for strict SunOS emulation */
if (O_NONBLOCK != O_NDELAY)
if (arg & O_NDELAY)
@@ -1031,7 +1037,7 @@ static int __init fcntl_init(void)
* Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
* is defined as O_NONBLOCK on some platforms and not on others.
*/
- BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
+ BUILD_BUG_ON(22 - 1 /* for O_RDONLY being 0 */ !=
HWEIGHT32(
(VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
__FMODE_EXEC | __FMODE_NONOTIFY));
@@ -2978,6 +2978,10 @@ static int may_open(const struct path *path, int acc_mode, int flag)
if (flag & O_NOATIME && !inode_owner_or_capable(inode))
return -EPERM;
+ /* O_ALLOW_ENCODED can only be set by superuser */
+ if ((flag & O_ALLOW_ENCODED) && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
return 0;
}
@@ -9,7 +9,7 @@
(O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \
O_APPEND | O_NDELAY | O_NONBLOCK | O_NDELAY | __O_SYNC | O_DSYNC | \
FASYNC | O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \
- O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE)
+ O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE | O_ALLOW_ENCODED)
#ifndef force_o_largefile
#define force_o_largefile() (!IS_ENABLED(CONFIG_ARCH_32BIT_OFF_T))
@@ -89,6 +89,10 @@
#define __O_TMPFILE 020000000
#endif
+#ifndef O_ALLOW_ENCODED
+#define O_ALLOW_ENCODED 040000000
+#endif
+
/* a horrid kludge trying to make sure that this will fail on old kernels */
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT)