@@ -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
@@ -19,6 +19,7 @@
#define O_PATH 020000000
#define __O_TMPFILE 040000000
+#define O_ALLOW_ENCODED 0100000000
#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. */
@@ -31,7 +31,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)
{
@@ -50,6 +51,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
if (!inode_owner_or_capable(file_mnt_user_ns(filp), 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)
@@ -1043,7 +1049,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));
@@ -3000,6 +3000,10 @@ static int may_open(struct user_namespace *mnt_userns, const struct path *path,
if (flag & O_NOATIME && !inode_owner_or_capable(mnt_userns, 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;
}
@@ -10,7 +10,7 @@
(O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \
O_APPEND | O_NDELAY | O_NONBLOCK | __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)
/* List of all valid flags for the how->upgrade_mask argument: */
#define VALID_UPGRADE_FLAGS \
@@ -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)