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: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
5fe0c23788
commit
f52e0c1130
29
fs/namei.c
29
fs/namei.c
|
@ -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)
|
||||||
|
|
||||||
result = tmp;
|
result = tmp;
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
__putname(tmp);
|
if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
|
||||||
result = ERR_PTR(retval);
|
__putname(tmp);
|
||||||
|
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,13 +1551,15 @@ static int path_init(int dfd, const char *name, unsigned int flags,
|
||||||
|
|
||||||
dentry = file->f_path.dentry;
|
dentry = file->f_path.dentry;
|
||||||
|
|
||||||
retval = -ENOTDIR;
|
if (*name) {
|
||||||
if (!S_ISDIR(dentry->d_inode->i_mode))
|
retval = -ENOTDIR;
|
||||||
goto fput_fail;
|
if (!S_ISDIR(dentry->d_inode->i_mode))
|
||||||
|
goto fput_fail;
|
||||||
|
|
||||||
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,
|
||||||
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 @@
|
||||||
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};
|
||||||
|
|
||||||
#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 *);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue