aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c146
1 files changed, 68 insertions, 78 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 4ea63ed5e791..09ce58e49e72 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -212,8 +212,7 @@ int generic_permission(struct inode *inode, int mask,
212 * Read/write DACs are always overridable. 212 * Read/write DACs are always overridable.
213 * Executable DACs are overridable if at least one exec bit is set. 213 * Executable DACs are overridable if at least one exec bit is set.
214 */ 214 */
215 if (!(mask & MAY_EXEC) || 215 if (!(mask & MAY_EXEC) || execute_ok(inode))
216 (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
217 if (capable(CAP_DAC_OVERRIDE)) 216 if (capable(CAP_DAC_OVERRIDE))
218 return 0; 217 return 0;
219 218
@@ -249,23 +248,11 @@ int inode_permission(struct inode *inode, int mask)
249 } 248 }
250 249
251 /* Ordinary permission routines do not understand MAY_APPEND. */ 250 /* Ordinary permission routines do not understand MAY_APPEND. */
252 if (inode->i_op && inode->i_op->permission) { 251 if (inode->i_op && inode->i_op->permission)
253 retval = inode->i_op->permission(inode, mask); 252 retval = inode->i_op->permission(inode, mask);
254 if (!retval) { 253 else
255 /*
256 * Exec permission on a regular file is denied if none
257 * of the execute bits are set.
258 *
259 * This check should be done by the ->permission()
260 * method.
261 */
262 if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) &&
263 !(inode->i_mode & S_IXUGO))
264 return -EACCES;
265 }
266 } else {
267 retval = generic_permission(inode, mask, NULL); 254 retval = generic_permission(inode, mask, NULL);
268 } 255
269 if (retval) 256 if (retval)
270 return retval; 257 return retval;
271 258
@@ -1106,6 +1093,15 @@ int path_lookup(const char *name, unsigned int flags,
1106 return do_path_lookup(AT_FDCWD, name, flags, nd); 1093 return do_path_lookup(AT_FDCWD, name, flags, nd);
1107} 1094}
1108 1095
1096int kern_path(const char *name, unsigned int flags, struct path *path)
1097{
1098 struct nameidata nd;
1099 int res = do_path_lookup(AT_FDCWD, name, flags, &nd);
1100 if (!res)
1101 *path = nd.path;
1102 return res;
1103}
1104
1109/** 1105/**
1110 * vfs_path_lookup - lookup a file path relative to a dentry-vfsmount pair 1106 * vfs_path_lookup - lookup a file path relative to a dentry-vfsmount pair
1111 * @dentry: pointer to dentry of the base directory 1107 * @dentry: pointer to dentry of the base directory
@@ -1138,9 +1134,16 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
1138 1134
1139} 1135}
1140 1136
1141static int __path_lookup_intent_open(int dfd, const char *name, 1137/**
1142 unsigned int lookup_flags, struct nameidata *nd, 1138 * path_lookup_open - lookup a file path with open intent
1143 int open_flags, int create_mode) 1139 * @dfd: the directory to use as base, or AT_FDCWD
1140 * @name: pointer to file name
1141 * @lookup_flags: lookup intent flags
1142 * @nd: pointer to nameidata
1143 * @open_flags: open intent flags
1144 */
1145int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags,
1146 struct nameidata *nd, int open_flags)
1144{ 1147{
1145 struct file *filp = get_empty_filp(); 1148 struct file *filp = get_empty_filp();
1146 int err; 1149 int err;
@@ -1149,7 +1152,7 @@ static int __path_lookup_intent_open(int dfd, const char *name,
1149 return -ENFILE; 1152 return -ENFILE;
1150 nd->intent.open.file = filp; 1153 nd->intent.open.file = filp;
1151 nd->intent.open.flags = open_flags; 1154 nd->intent.open.flags = open_flags;
1152 nd->intent.open.create_mode = create_mode; 1155 nd->intent.open.create_mode = 0;
1153 err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd); 1156 err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
1154 if (IS_ERR(nd->intent.open.file)) { 1157 if (IS_ERR(nd->intent.open.file)) {
1155 if (err == 0) { 1158 if (err == 0) {
@@ -1161,38 +1164,6 @@ static int __path_lookup_intent_open(int dfd, const char *name,
1161 return err; 1164 return err;
1162} 1165}
1163 1166
1164/**
1165 * path_lookup_open - lookup a file path with open intent
1166 * @dfd: the directory to use as base, or AT_FDCWD
1167 * @name: pointer to file name
1168 * @lookup_flags: lookup intent flags
1169 * @nd: pointer to nameidata
1170 * @open_flags: open intent flags
1171 */
1172int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags,
1173 struct nameidata *nd, int open_flags)
1174{
1175 return __path_lookup_intent_open(dfd, name, lookup_flags, nd,
1176 open_flags, 0);
1177}
1178
1179/**
1180 * path_lookup_create - lookup a file path with open + create intent
1181 * @dfd: the directory to use as base, or AT_FDCWD
1182 * @name: pointer to file name
1183 * @lookup_flags: lookup intent flags
1184 * @nd: pointer to nameidata
1185 * @open_flags: open intent flags
1186 * @create_mode: create intent flags
1187 */
1188static int path_lookup_create(int dfd, const char *name,
1189 unsigned int lookup_flags, struct nameidata *nd,
1190 int open_flags, int create_mode)
1191{
1192 return __path_lookup_intent_open(dfd, name, lookup_flags|LOOKUP_CREATE,
1193 nd, open_flags, create_mode);
1194}
1195
1196static struct dentry *__lookup_hash(struct qstr *name, 1167static struct dentry *__lookup_hash(struct qstr *name,
1197 struct dentry *base, struct nameidata *nd) 1168 struct dentry *base, struct nameidata *nd)
1198{ 1169{
@@ -1470,20 +1441,18 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
1470 1441
1471 mutex_lock(&p1->d_inode->i_sb->s_vfs_rename_mutex); 1442 mutex_lock(&p1->d_inode->i_sb->s_vfs_rename_mutex);
1472 1443
1473 for (p = p1; p->d_parent != p; p = p->d_parent) { 1444 p = d_ancestor(p2, p1);
1474 if (p->d_parent == p2) { 1445 if (p) {
1475 mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_PARENT); 1446 mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_PARENT);
1476 mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_CHILD); 1447 mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_CHILD);
1477 return p; 1448 return p;
1478 }
1479 } 1449 }
1480 1450
1481 for (p = p2; p->d_parent != p; p = p->d_parent) { 1451 p = d_ancestor(p1, p2);
1482 if (p->d_parent == p1) { 1452 if (p) {
1483 mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT); 1453 mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT);
1484 mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD); 1454 mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD);
1485 return p; 1455 return p;
1486 }
1487 } 1456 }
1488 1457
1489 mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT); 1458 mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT);
@@ -1702,8 +1671,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
1702 /* 1671 /*
1703 * Create - we need to know the parent. 1672 * Create - we need to know the parent.
1704 */ 1673 */
1705 error = path_lookup_create(dfd, pathname, LOOKUP_PARENT, 1674 error = do_path_lookup(dfd, pathname, LOOKUP_PARENT, &nd);
1706 &nd, flag, mode);
1707 if (error) 1675 if (error)
1708 return ERR_PTR(error); 1676 return ERR_PTR(error);
1709 1677
@@ -1714,10 +1682,20 @@ struct file *do_filp_open(int dfd, const char *pathname,
1714 */ 1682 */
1715 error = -EISDIR; 1683 error = -EISDIR;
1716 if (nd.last_type != LAST_NORM || nd.last.name[nd.last.len]) 1684 if (nd.last_type != LAST_NORM || nd.last.name[nd.last.len])
1717 goto exit; 1685 goto exit_parent;
1718 1686
1687 error = -ENFILE;
1688 filp = get_empty_filp();
1689 if (filp == NULL)
1690 goto exit_parent;
1691 nd.intent.open.file = filp;
1692 nd.intent.open.flags = flag;
1693 nd.intent.open.create_mode = mode;
1719 dir = nd.path.dentry; 1694 dir = nd.path.dentry;
1720 nd.flags &= ~LOOKUP_PARENT; 1695 nd.flags &= ~LOOKUP_PARENT;
1696 nd.flags |= LOOKUP_CREATE | LOOKUP_OPEN;
1697 if (flag & O_EXCL)
1698 nd.flags |= LOOKUP_EXCL;
1721 mutex_lock(&dir->d_inode->i_mutex); 1699 mutex_lock(&dir->d_inode->i_mutex);
1722 path.dentry = lookup_hash(&nd); 1700 path.dentry = lookup_hash(&nd);
1723 path.mnt = nd.path.mnt; 1701 path.mnt = nd.path.mnt;
@@ -1822,6 +1800,7 @@ exit_dput:
1822exit: 1800exit:
1823 if (!IS_ERR(nd.intent.open.file)) 1801 if (!IS_ERR(nd.intent.open.file))
1824 release_open_intent(&nd); 1802 release_open_intent(&nd);
1803exit_parent:
1825 path_put(&nd.path); 1804 path_put(&nd.path);
1826 return ERR_PTR(error); 1805 return ERR_PTR(error);
1827 1806
@@ -1914,7 +1893,7 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir)
1914 if (nd->last_type != LAST_NORM) 1893 if (nd->last_type != LAST_NORM)
1915 goto fail; 1894 goto fail;
1916 nd->flags &= ~LOOKUP_PARENT; 1895 nd->flags &= ~LOOKUP_PARENT;
1917 nd->flags |= LOOKUP_CREATE; 1896 nd->flags |= LOOKUP_CREATE | LOOKUP_EXCL;
1918 nd->intent.open.flags = O_EXCL; 1897 nd->intent.open.flags = O_EXCL;
1919 1898
1920 /* 1899 /*
@@ -2178,16 +2157,19 @@ static long do_rmdir(int dfd, const char __user *pathname)
2178 return error; 2157 return error;
2179 2158
2180 switch(nd.last_type) { 2159 switch(nd.last_type) {
2181 case LAST_DOTDOT: 2160 case LAST_DOTDOT:
2182 error = -ENOTEMPTY; 2161 error = -ENOTEMPTY;
2183 goto exit1; 2162 goto exit1;
2184 case LAST_DOT: 2163 case LAST_DOT:
2185 error = -EINVAL; 2164 error = -EINVAL;
2186 goto exit1; 2165 goto exit1;
2187 case LAST_ROOT: 2166 case LAST_ROOT:
2188 error = -EBUSY; 2167 error = -EBUSY;
2189 goto exit1; 2168 goto exit1;
2190 } 2169 }
2170
2171 nd.flags &= ~LOOKUP_PARENT;
2172
2191 mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); 2173 mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
2192 dentry = lookup_hash(&nd); 2174 dentry = lookup_hash(&nd);
2193 error = PTR_ERR(dentry); 2175 error = PTR_ERR(dentry);
@@ -2265,6 +2247,9 @@ static long do_unlinkat(int dfd, const char __user *pathname)
2265 error = -EISDIR; 2247 error = -EISDIR;
2266 if (nd.last_type != LAST_NORM) 2248 if (nd.last_type != LAST_NORM)
2267 goto exit1; 2249 goto exit1;
2250
2251 nd.flags &= ~LOOKUP_PARENT;
2252
2268 mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); 2253 mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
2269 dentry = lookup_hash(&nd); 2254 dentry = lookup_hash(&nd);
2270 error = PTR_ERR(dentry); 2255 error = PTR_ERR(dentry);
@@ -2654,6 +2639,10 @@ asmlinkage long sys_renameat(int olddfd, const char __user *oldname,
2654 if (newnd.last_type != LAST_NORM) 2639 if (newnd.last_type != LAST_NORM)
2655 goto exit2; 2640 goto exit2;
2656 2641
2642 oldnd.flags &= ~LOOKUP_PARENT;
2643 newnd.flags &= ~LOOKUP_PARENT;
2644 newnd.flags |= LOOKUP_RENAME_TARGET;
2645
2657 trap = lock_rename(new_dir, old_dir); 2646 trap = lock_rename(new_dir, old_dir);
2658 2647
2659 old_dentry = lookup_hash(&oldnd); 2648 old_dentry = lookup_hash(&oldnd);
@@ -2855,6 +2844,7 @@ EXPORT_SYMBOL(__page_symlink);
2855EXPORT_SYMBOL(page_symlink); 2844EXPORT_SYMBOL(page_symlink);
2856EXPORT_SYMBOL(page_symlink_inode_operations); 2845EXPORT_SYMBOL(page_symlink_inode_operations);
2857EXPORT_SYMBOL(path_lookup); 2846EXPORT_SYMBOL(path_lookup);
2847EXPORT_SYMBOL(kern_path);
2858EXPORT_SYMBOL(vfs_path_lookup); 2848EXPORT_SYMBOL(vfs_path_lookup);
2859EXPORT_SYMBOL(inode_permission); 2849EXPORT_SYMBOL(inode_permission);
2860EXPORT_SYMBOL(vfs_permission); 2850EXPORT_SYMBOL(vfs_permission);