Commit f52e0c11 authored by Al Viro's avatar Al Viro

New AT_... flag: AT_EMPTY_PATH

For name_to_handle_at(2) we'll want both ...at()-style syscall that
would be usable for non-directory descriptors (with empty relative
pathname).  Introduce new flag (AT_EMPTY_PATH) to deal with that and
corresponding LOOKUP_EMPTY; teach user_path_at() and path_init() to
deal with the latter.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 5fe0c237
...@@ -136,7 +136,7 @@ static int do_getname(const char __user *filename, char *page) ...@@ -136,7 +136,7 @@ static int do_getname(const char __user *filename, char *page)
return retval; return retval;
} }
char * getname(const char __user * filename) static char *getname_flags(const char __user * filename, int flags)
{ {
char *tmp, *result; char *tmp, *result;
...@@ -147,14 +147,21 @@ char * getname(const char __user * filename) ...@@ -147,14 +147,21 @@ char * getname(const char __user * filename)
result = tmp; result = tmp;
if (retval < 0) { if (retval < 0) {
if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
__putname(tmp); __putname(tmp);
result = ERR_PTR(retval); result = ERR_PTR(retval);
} }
} }
}
audit_getname(result); audit_getname(result);
return result; return result;
} }
char *getname(const char __user * filename)
{
return getname_flags(filename, 0);
}
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
void putname(const char *name) void putname(const char *name)
{ {
...@@ -1544,6 +1551,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, ...@@ -1544,6 +1551,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
dentry = file->f_path.dentry; dentry = file->f_path.dentry;
if (*name) {
retval = -ENOTDIR; retval = -ENOTDIR;
if (!S_ISDIR(dentry->d_inode->i_mode)) if (!S_ISDIR(dentry->d_inode->i_mode))
goto fput_fail; goto fput_fail;
...@@ -1551,6 +1559,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, ...@@ -1551,6 +1559,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
retval = file_permission(file, MAY_EXEC); retval = file_permission(file, MAY_EXEC);
if (retval) if (retval)
goto fput_fail; goto fput_fail;
}
nd->path = file->f_path; nd->path = file->f_path;
if (flags & LOOKUP_RCU) { if (flags & LOOKUP_RCU) {
...@@ -1759,7 +1768,7 @@ int user_path_at(int dfd, const char __user *name, unsigned flags, ...@@ -1759,7 +1768,7 @@ int user_path_at(int dfd, const char __user *name, unsigned flags,
struct path *path) struct path *path)
{ {
struct nameidata nd; struct nameidata nd;
char *tmp = getname(name); char *tmp = getname_flags(name, flags);
int err = PTR_ERR(tmp); int err = PTR_ERR(tmp);
if (!IS_ERR(tmp)) { if (!IS_ERR(tmp)) {
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
unlinking file. */ unlinking file. */
#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */ #define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
#define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */ #define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */
#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
#ifdef __KERNEL__ #ifdef __KERNEL__
......
...@@ -64,6 +64,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; ...@@ -64,6 +64,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
#define LOOKUP_JUMPED 0x1000 #define LOOKUP_JUMPED 0x1000
#define LOOKUP_ROOT 0x2000 #define LOOKUP_ROOT 0x2000
#define LOOKUP_EMPTY 0x4000
extern int user_path_at(int, const char __user *, unsigned, struct path *); extern int user_path_at(int, const char __user *, unsigned, struct path *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment