diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 354 |
1 files changed, 118 insertions, 236 deletions
diff --git a/fs/namei.c b/fs/namei.c index 01e67dddcc3d..a7b0a0b80128 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/file.h> | 31 | #include <linux/file.h> |
32 | #include <linux/fcntl.h> | 32 | #include <linux/fcntl.h> |
33 | #include <linux/device_cgroup.h> | 33 | #include <linux/device_cgroup.h> |
34 | #include <asm/namei.h> | ||
35 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
36 | 35 | ||
37 | #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) | 36 | #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) |
@@ -185,6 +184,8 @@ int generic_permission(struct inode *inode, int mask, | |||
185 | { | 184 | { |
186 | umode_t mode = inode->i_mode; | 185 | umode_t mode = inode->i_mode; |
187 | 186 | ||
187 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; | ||
188 | |||
188 | if (current->fsuid == inode->i_uid) | 189 | if (current->fsuid == inode->i_uid) |
189 | mode >>= 6; | 190 | mode >>= 6; |
190 | else { | 191 | else { |
@@ -203,7 +204,7 @@ int generic_permission(struct inode *inode, int mask, | |||
203 | /* | 204 | /* |
204 | * If the DACs are ok we don't need any capability check. | 205 | * If the DACs are ok we don't need any capability check. |
205 | */ | 206 | */ |
206 | if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)) | 207 | if ((mask & ~mode) == 0) |
207 | return 0; | 208 | return 0; |
208 | 209 | ||
209 | check_capabilities: | 210 | check_capabilities: |
@@ -226,13 +227,9 @@ int generic_permission(struct inode *inode, int mask, | |||
226 | return -EACCES; | 227 | return -EACCES; |
227 | } | 228 | } |
228 | 229 | ||
229 | int permission(struct inode *inode, int mask, struct nameidata *nd) | 230 | int inode_permission(struct inode *inode, int mask) |
230 | { | 231 | { |
231 | int retval, submask; | 232 | int retval; |
232 | struct vfsmount *mnt = NULL; | ||
233 | |||
234 | if (nd) | ||
235 | mnt = nd->path.mnt; | ||
236 | 233 | ||
237 | if (mask & MAY_WRITE) { | 234 | if (mask & MAY_WRITE) { |
238 | umode_t mode = inode->i_mode; | 235 | umode_t mode = inode->i_mode; |
@@ -251,19 +248,9 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
251 | return -EACCES; | 248 | return -EACCES; |
252 | } | 249 | } |
253 | 250 | ||
254 | if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { | ||
255 | /* | ||
256 | * MAY_EXEC on regular files is denied if the fs is mounted | ||
257 | * with the "noexec" flag. | ||
258 | */ | ||
259 | if (mnt && (mnt->mnt_flags & MNT_NOEXEC)) | ||
260 | return -EACCES; | ||
261 | } | ||
262 | |||
263 | /* Ordinary permission routines do not understand MAY_APPEND. */ | 251 | /* Ordinary permission routines do not understand MAY_APPEND. */ |
264 | submask = mask & ~MAY_APPEND; | ||
265 | if (inode->i_op && inode->i_op->permission) { | 252 | if (inode->i_op && inode->i_op->permission) { |
266 | retval = inode->i_op->permission(inode, submask, nd); | 253 | retval = inode->i_op->permission(inode, mask); |
267 | if (!retval) { | 254 | if (!retval) { |
268 | /* | 255 | /* |
269 | * Exec permission on a regular file is denied if none | 256 | * Exec permission on a regular file is denied if none |
@@ -277,7 +264,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
277 | return -EACCES; | 264 | return -EACCES; |
278 | } | 265 | } |
279 | } else { | 266 | } else { |
280 | retval = generic_permission(inode, submask, NULL); | 267 | retval = generic_permission(inode, mask, NULL); |
281 | } | 268 | } |
282 | if (retval) | 269 | if (retval) |
283 | return retval; | 270 | return retval; |
@@ -286,7 +273,8 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
286 | if (retval) | 273 | if (retval) |
287 | return retval; | 274 | return retval; |
288 | 275 | ||
289 | return security_inode_permission(inode, mask, nd); | 276 | return security_inode_permission(inode, |
277 | mask & (MAY_READ|MAY_WRITE|MAY_EXEC)); | ||
290 | } | 278 | } |
291 | 279 | ||
292 | /** | 280 | /** |
@@ -301,7 +289,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
301 | */ | 289 | */ |
302 | int vfs_permission(struct nameidata *nd, int mask) | 290 | int vfs_permission(struct nameidata *nd, int mask) |
303 | { | 291 | { |
304 | return permission(nd->path.dentry->d_inode, mask, nd); | 292 | return inode_permission(nd->path.dentry->d_inode, mask); |
305 | } | 293 | } |
306 | 294 | ||
307 | /** | 295 | /** |
@@ -318,7 +306,7 @@ int vfs_permission(struct nameidata *nd, int mask) | |||
318 | */ | 306 | */ |
319 | int file_permission(struct file *file, int mask) | 307 | int file_permission(struct file *file, int mask) |
320 | { | 308 | { |
321 | return permission(file->f_path.dentry->d_inode, mask, NULL); | 309 | return inode_permission(file->f_path.dentry->d_inode, mask); |
322 | } | 310 | } |
323 | 311 | ||
324 | /* | 312 | /* |
@@ -459,8 +447,7 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, | |||
459 | * short-cut DAC fails, then call permission() to do more | 447 | * short-cut DAC fails, then call permission() to do more |
460 | * complete permission check. | 448 | * complete permission check. |
461 | */ | 449 | */ |
462 | static int exec_permission_lite(struct inode *inode, | 450 | static int exec_permission_lite(struct inode *inode) |
463 | struct nameidata *nd) | ||
464 | { | 451 | { |
465 | umode_t mode = inode->i_mode; | 452 | umode_t mode = inode->i_mode; |
466 | 453 | ||
@@ -486,7 +473,7 @@ static int exec_permission_lite(struct inode *inode, | |||
486 | 473 | ||
487 | return -EACCES; | 474 | return -EACCES; |
488 | ok: | 475 | ok: |
489 | return security_inode_permission(inode, MAY_EXEC, nd); | 476 | return security_inode_permission(inode, MAY_EXEC); |
490 | } | 477 | } |
491 | 478 | ||
492 | /* | 479 | /* |
@@ -519,7 +506,14 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
519 | */ | 506 | */ |
520 | result = d_lookup(parent, name); | 507 | result = d_lookup(parent, name); |
521 | if (!result) { | 508 | if (!result) { |
522 | struct dentry * dentry = d_alloc(parent, name); | 509 | struct dentry *dentry; |
510 | |||
511 | /* Don't create child dentry for a dead directory. */ | ||
512 | result = ERR_PTR(-ENOENT); | ||
513 | if (IS_DEADDIR(dir)) | ||
514 | goto out_unlock; | ||
515 | |||
516 | dentry = d_alloc(parent, name); | ||
523 | result = ERR_PTR(-ENOMEM); | 517 | result = ERR_PTR(-ENOMEM); |
524 | if (dentry) { | 518 | if (dentry) { |
525 | result = dir->i_op->lookup(dir, dentry, nd); | 519 | result = dir->i_op->lookup(dir, dentry, nd); |
@@ -528,6 +522,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
528 | else | 522 | else |
529 | result = dentry; | 523 | result = dentry; |
530 | } | 524 | } |
525 | out_unlock: | ||
531 | mutex_unlock(&dir->i_mutex); | 526 | mutex_unlock(&dir->i_mutex); |
532 | return result; | 527 | return result; |
533 | } | 528 | } |
@@ -545,27 +540,16 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
545 | return result; | 540 | return result; |
546 | } | 541 | } |
547 | 542 | ||
548 | static int __emul_lookup_dentry(const char *, struct nameidata *); | ||
549 | |||
550 | /* SMP-safe */ | 543 | /* SMP-safe */ |
551 | static __always_inline int | 544 | static __always_inline void |
552 | walk_init_root(const char *name, struct nameidata *nd) | 545 | walk_init_root(const char *name, struct nameidata *nd) |
553 | { | 546 | { |
554 | struct fs_struct *fs = current->fs; | 547 | struct fs_struct *fs = current->fs; |
555 | 548 | ||
556 | read_lock(&fs->lock); | 549 | read_lock(&fs->lock); |
557 | if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) { | ||
558 | nd->path = fs->altroot; | ||
559 | path_get(&fs->altroot); | ||
560 | read_unlock(&fs->lock); | ||
561 | if (__emul_lookup_dentry(name,nd)) | ||
562 | return 0; | ||
563 | read_lock(&fs->lock); | ||
564 | } | ||
565 | nd->path = fs->root; | 550 | nd->path = fs->root; |
566 | path_get(&fs->root); | 551 | path_get(&fs->root); |
567 | read_unlock(&fs->lock); | 552 | read_unlock(&fs->lock); |
568 | return 1; | ||
569 | } | 553 | } |
570 | 554 | ||
571 | /* | 555 | /* |
@@ -606,12 +590,9 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l | |||
606 | 590 | ||
607 | if (*link == '/') { | 591 | if (*link == '/') { |
608 | path_put(&nd->path); | 592 | path_put(&nd->path); |
609 | if (!walk_init_root(link, nd)) | 593 | walk_init_root(link, nd); |
610 | /* weird __emul_prefix() stuff did it */ | ||
611 | goto out; | ||
612 | } | 594 | } |
613 | res = link_path_walk(link, nd); | 595 | res = link_path_walk(link, nd); |
614 | out: | ||
615 | if (nd->depth || res || nd->last_type!=LAST_NORM) | 596 | if (nd->depth || res || nd->last_type!=LAST_NORM) |
616 | return res; | 597 | return res; |
617 | /* | 598 | /* |
@@ -889,7 +870,7 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
889 | unsigned int c; | 870 | unsigned int c; |
890 | 871 | ||
891 | nd->flags |= LOOKUP_CONTINUE; | 872 | nd->flags |= LOOKUP_CONTINUE; |
892 | err = exec_permission_lite(inode, nd); | 873 | err = exec_permission_lite(inode); |
893 | if (err == -EAGAIN) | 874 | if (err == -EAGAIN) |
894 | err = vfs_permission(nd, MAY_EXEC); | 875 | err = vfs_permission(nd, MAY_EXEC); |
895 | if (err) | 876 | if (err) |
@@ -1060,67 +1041,6 @@ static int path_walk(const char *name, struct nameidata *nd) | |||
1060 | return link_path_walk(name, nd); | 1041 | return link_path_walk(name, nd); |
1061 | } | 1042 | } |
1062 | 1043 | ||
1063 | /* | ||
1064 | * SMP-safe: Returns 1 and nd will have valid dentry and mnt, if | ||
1065 | * everything is done. Returns 0 and drops input nd, if lookup failed; | ||
1066 | */ | ||
1067 | static int __emul_lookup_dentry(const char *name, struct nameidata *nd) | ||
1068 | { | ||
1069 | if (path_walk(name, nd)) | ||
1070 | return 0; /* something went wrong... */ | ||
1071 | |||
1072 | if (!nd->path.dentry->d_inode || | ||
1073 | S_ISDIR(nd->path.dentry->d_inode->i_mode)) { | ||
1074 | struct path old_path = nd->path; | ||
1075 | struct qstr last = nd->last; | ||
1076 | int last_type = nd->last_type; | ||
1077 | struct fs_struct *fs = current->fs; | ||
1078 | |||
1079 | /* | ||
1080 | * NAME was not found in alternate root or it's a directory. | ||
1081 | * Try to find it in the normal root: | ||
1082 | */ | ||
1083 | nd->last_type = LAST_ROOT; | ||
1084 | read_lock(&fs->lock); | ||
1085 | nd->path = fs->root; | ||
1086 | path_get(&fs->root); | ||
1087 | read_unlock(&fs->lock); | ||
1088 | if (path_walk(name, nd) == 0) { | ||
1089 | if (nd->path.dentry->d_inode) { | ||
1090 | path_put(&old_path); | ||
1091 | return 1; | ||
1092 | } | ||
1093 | path_put(&nd->path); | ||
1094 | } | ||
1095 | nd->path = old_path; | ||
1096 | nd->last = last; | ||
1097 | nd->last_type = last_type; | ||
1098 | } | ||
1099 | return 1; | ||
1100 | } | ||
1101 | |||
1102 | void set_fs_altroot(void) | ||
1103 | { | ||
1104 | char *emul = __emul_prefix(); | ||
1105 | struct nameidata nd; | ||
1106 | struct path path = {}, old_path; | ||
1107 | int err; | ||
1108 | struct fs_struct *fs = current->fs; | ||
1109 | |||
1110 | if (!emul) | ||
1111 | goto set_it; | ||
1112 | err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd); | ||
1113 | if (!err) | ||
1114 | path = nd.path; | ||
1115 | set_it: | ||
1116 | write_lock(&fs->lock); | ||
1117 | old_path = fs->altroot; | ||
1118 | fs->altroot = path; | ||
1119 | write_unlock(&fs->lock); | ||
1120 | if (old_path.dentry) | ||
1121 | path_put(&old_path); | ||
1122 | } | ||
1123 | |||
1124 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ | 1044 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ |
1125 | static int do_path_lookup(int dfd, const char *name, | 1045 | static int do_path_lookup(int dfd, const char *name, |
1126 | unsigned int flags, struct nameidata *nd) | 1046 | unsigned int flags, struct nameidata *nd) |
@@ -1136,14 +1056,6 @@ static int do_path_lookup(int dfd, const char *name, | |||
1136 | 1056 | ||
1137 | if (*name=='/') { | 1057 | if (*name=='/') { |
1138 | read_lock(&fs->lock); | 1058 | read_lock(&fs->lock); |
1139 | if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) { | ||
1140 | nd->path = fs->altroot; | ||
1141 | path_get(&fs->altroot); | ||
1142 | read_unlock(&fs->lock); | ||
1143 | if (__emul_lookup_dentry(name,nd)) | ||
1144 | goto out; /* found in altroot */ | ||
1145 | read_lock(&fs->lock); | ||
1146 | } | ||
1147 | nd->path = fs->root; | 1059 | nd->path = fs->root; |
1148 | path_get(&fs->root); | 1060 | path_get(&fs->root); |
1149 | read_unlock(&fs->lock); | 1061 | read_unlock(&fs->lock); |
@@ -1177,7 +1089,6 @@ static int do_path_lookup(int dfd, const char *name, | |||
1177 | } | 1089 | } |
1178 | 1090 | ||
1179 | retval = path_walk(name, nd); | 1091 | retval = path_walk(name, nd); |
1180 | out: | ||
1181 | if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && | 1092 | if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && |
1182 | nd->path.dentry->d_inode)) | 1093 | nd->path.dentry->d_inode)) |
1183 | audit_inode(name, nd->path.dentry); | 1094 | audit_inode(name, nd->path.dentry); |
@@ -1282,19 +1193,6 @@ static int path_lookup_create(int dfd, const char *name, | |||
1282 | nd, open_flags, create_mode); | 1193 | nd, open_flags, create_mode); |
1283 | } | 1194 | } |
1284 | 1195 | ||
1285 | int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags, | ||
1286 | struct nameidata *nd, int open_flags) | ||
1287 | { | ||
1288 | char *tmp = getname(name); | ||
1289 | int err = PTR_ERR(tmp); | ||
1290 | |||
1291 | if (!IS_ERR(tmp)) { | ||
1292 | err = __path_lookup_intent_open(AT_FDCWD, tmp, lookup_flags, nd, open_flags, 0); | ||
1293 | putname(tmp); | ||
1294 | } | ||
1295 | return err; | ||
1296 | } | ||
1297 | |||
1298 | static struct dentry *__lookup_hash(struct qstr *name, | 1196 | static struct dentry *__lookup_hash(struct qstr *name, |
1299 | struct dentry *base, struct nameidata *nd) | 1197 | struct dentry *base, struct nameidata *nd) |
1300 | { | 1198 | { |
@@ -1317,7 +1215,14 @@ static struct dentry *__lookup_hash(struct qstr *name, | |||
1317 | 1215 | ||
1318 | dentry = cached_lookup(base, name, nd); | 1216 | dentry = cached_lookup(base, name, nd); |
1319 | if (!dentry) { | 1217 | if (!dentry) { |
1320 | struct dentry *new = d_alloc(base, name); | 1218 | struct dentry *new; |
1219 | |||
1220 | /* Don't create child dentry for a dead directory. */ | ||
1221 | dentry = ERR_PTR(-ENOENT); | ||
1222 | if (IS_DEADDIR(inode)) | ||
1223 | goto out; | ||
1224 | |||
1225 | new = d_alloc(base, name); | ||
1321 | dentry = ERR_PTR(-ENOMEM); | 1226 | dentry = ERR_PTR(-ENOMEM); |
1322 | if (!new) | 1227 | if (!new) |
1323 | goto out; | 1228 | goto out; |
@@ -1340,7 +1245,7 @@ static struct dentry *lookup_hash(struct nameidata *nd) | |||
1340 | { | 1245 | { |
1341 | int err; | 1246 | int err; |
1342 | 1247 | ||
1343 | err = permission(nd->path.dentry->d_inode, MAY_EXEC, nd); | 1248 | err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC); |
1344 | if (err) | 1249 | if (err) |
1345 | return ERR_PTR(err); | 1250 | return ERR_PTR(err); |
1346 | return __lookup_hash(&nd->last, nd->path.dentry, nd); | 1251 | return __lookup_hash(&nd->last, nd->path.dentry, nd); |
@@ -1388,7 +1293,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | |||
1388 | if (err) | 1293 | if (err) |
1389 | return ERR_PTR(err); | 1294 | return ERR_PTR(err); |
1390 | 1295 | ||
1391 | err = permission(base->d_inode, MAY_EXEC, NULL); | 1296 | err = inode_permission(base->d_inode, MAY_EXEC); |
1392 | if (err) | 1297 | if (err) |
1393 | return ERR_PTR(err); | 1298 | return ERR_PTR(err); |
1394 | return __lookup_hash(&this, base, NULL); | 1299 | return __lookup_hash(&this, base, NULL); |
@@ -1416,22 +1321,40 @@ struct dentry *lookup_one_noperm(const char *name, struct dentry *base) | |||
1416 | return __lookup_hash(&this, base, NULL); | 1321 | return __lookup_hash(&this, base, NULL); |
1417 | } | 1322 | } |
1418 | 1323 | ||
1419 | int __user_walk_fd(int dfd, const char __user *name, unsigned flags, | 1324 | int user_path_at(int dfd, const char __user *name, unsigned flags, |
1420 | struct nameidata *nd) | 1325 | struct path *path) |
1421 | { | 1326 | { |
1327 | struct nameidata nd; | ||
1422 | char *tmp = getname(name); | 1328 | char *tmp = getname(name); |
1423 | int err = PTR_ERR(tmp); | 1329 | int err = PTR_ERR(tmp); |
1424 | |||
1425 | if (!IS_ERR(tmp)) { | 1330 | if (!IS_ERR(tmp)) { |
1426 | err = do_path_lookup(dfd, tmp, flags, nd); | 1331 | |
1332 | BUG_ON(flags & LOOKUP_PARENT); | ||
1333 | |||
1334 | err = do_path_lookup(dfd, tmp, flags, &nd); | ||
1427 | putname(tmp); | 1335 | putname(tmp); |
1336 | if (!err) | ||
1337 | *path = nd.path; | ||
1428 | } | 1338 | } |
1429 | return err; | 1339 | return err; |
1430 | } | 1340 | } |
1431 | 1341 | ||
1432 | int __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) | 1342 | static int user_path_parent(int dfd, const char __user *path, |
1343 | struct nameidata *nd, char **name) | ||
1433 | { | 1344 | { |
1434 | return __user_walk_fd(AT_FDCWD, name, flags, nd); | 1345 | char *s = getname(path); |
1346 | int error; | ||
1347 | |||
1348 | if (IS_ERR(s)) | ||
1349 | return PTR_ERR(s); | ||
1350 | |||
1351 | error = do_path_lookup(dfd, s, LOOKUP_PARENT, nd); | ||
1352 | if (error) | ||
1353 | putname(s); | ||
1354 | else | ||
1355 | *name = s; | ||
1356 | |||
1357 | return error; | ||
1435 | } | 1358 | } |
1436 | 1359 | ||
1437 | /* | 1360 | /* |
@@ -1478,7 +1401,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) | |||
1478 | BUG_ON(victim->d_parent->d_inode != dir); | 1401 | BUG_ON(victim->d_parent->d_inode != dir); |
1479 | audit_inode_child(victim->d_name.name, victim, dir); | 1402 | audit_inode_child(victim->d_name.name, victim, dir); |
1480 | 1403 | ||
1481 | error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); | 1404 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); |
1482 | if (error) | 1405 | if (error) |
1483 | return error; | 1406 | return error; |
1484 | if (IS_APPEND(dir)) | 1407 | if (IS_APPEND(dir)) |
@@ -1515,7 +1438,7 @@ static inline int may_create(struct inode *dir, struct dentry *child, | |||
1515 | return -EEXIST; | 1438 | return -EEXIST; |
1516 | if (IS_DEADDIR(dir)) | 1439 | if (IS_DEADDIR(dir)) |
1517 | return -ENOENT; | 1440 | return -ENOENT; |
1518 | return permission(dir,MAY_WRITE | MAY_EXEC, nd); | 1441 | return inode_permission(dir, MAY_WRITE | MAY_EXEC); |
1519 | } | 1442 | } |
1520 | 1443 | ||
1521 | /* | 1444 | /* |
@@ -1755,7 +1678,7 @@ struct file *do_filp_open(int dfd, const char *pathname, | |||
1755 | int will_write; | 1678 | int will_write; |
1756 | int flag = open_to_namei_flags(open_flag); | 1679 | int flag = open_to_namei_flags(open_flag); |
1757 | 1680 | ||
1758 | acc_mode = ACC_MODE(flag); | 1681 | acc_mode = MAY_OPEN | ACC_MODE(flag); |
1759 | 1682 | ||
1760 | /* O_TRUNC implies we need access checks for write permissions */ | 1683 | /* O_TRUNC implies we need access checks for write permissions */ |
1761 | if (flag & O_TRUNC) | 1684 | if (flag & O_TRUNC) |
@@ -2071,20 +1994,18 @@ static int may_mknod(mode_t mode) | |||
2071 | asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | 1994 | asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, |
2072 | unsigned dev) | 1995 | unsigned dev) |
2073 | { | 1996 | { |
2074 | int error = 0; | 1997 | int error; |
2075 | char * tmp; | 1998 | char *tmp; |
2076 | struct dentry * dentry; | 1999 | struct dentry *dentry; |
2077 | struct nameidata nd; | 2000 | struct nameidata nd; |
2078 | 2001 | ||
2079 | if (S_ISDIR(mode)) | 2002 | if (S_ISDIR(mode)) |
2080 | return -EPERM; | 2003 | return -EPERM; |
2081 | tmp = getname(filename); | ||
2082 | if (IS_ERR(tmp)) | ||
2083 | return PTR_ERR(tmp); | ||
2084 | 2004 | ||
2085 | error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); | 2005 | error = user_path_parent(dfd, filename, &nd, &tmp); |
2086 | if (error) | 2006 | if (error) |
2087 | goto out; | 2007 | return error; |
2008 | |||
2088 | dentry = lookup_create(&nd, 0); | 2009 | dentry = lookup_create(&nd, 0); |
2089 | if (IS_ERR(dentry)) { | 2010 | if (IS_ERR(dentry)) { |
2090 | error = PTR_ERR(dentry); | 2011 | error = PTR_ERR(dentry); |
@@ -2116,7 +2037,6 @@ out_dput: | |||
2116 | out_unlock: | 2037 | out_unlock: |
2117 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2038 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2118 | path_put(&nd.path); | 2039 | path_put(&nd.path); |
2119 | out: | ||
2120 | putname(tmp); | 2040 | putname(tmp); |
2121 | 2041 | ||
2122 | return error; | 2042 | return error; |
@@ -2156,14 +2076,10 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
2156 | struct dentry *dentry; | 2076 | struct dentry *dentry; |
2157 | struct nameidata nd; | 2077 | struct nameidata nd; |
2158 | 2078 | ||
2159 | tmp = getname(pathname); | 2079 | error = user_path_parent(dfd, pathname, &nd, &tmp); |
2160 | error = PTR_ERR(tmp); | 2080 | if (error) |
2161 | if (IS_ERR(tmp)) | ||
2162 | goto out_err; | 2081 | goto out_err; |
2163 | 2082 | ||
2164 | error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); | ||
2165 | if (error) | ||
2166 | goto out; | ||
2167 | dentry = lookup_create(&nd, 1); | 2083 | dentry = lookup_create(&nd, 1); |
2168 | error = PTR_ERR(dentry); | 2084 | error = PTR_ERR(dentry); |
2169 | if (IS_ERR(dentry)) | 2085 | if (IS_ERR(dentry)) |
@@ -2181,7 +2097,6 @@ out_dput: | |||
2181 | out_unlock: | 2097 | out_unlock: |
2182 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2098 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2183 | path_put(&nd.path); | 2099 | path_put(&nd.path); |
2184 | out: | ||
2185 | putname(tmp); | 2100 | putname(tmp); |
2186 | out_err: | 2101 | out_err: |
2187 | return error; | 2102 | return error; |
@@ -2259,13 +2174,9 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
2259 | struct dentry *dentry; | 2174 | struct dentry *dentry; |
2260 | struct nameidata nd; | 2175 | struct nameidata nd; |
2261 | 2176 | ||
2262 | name = getname(pathname); | 2177 | error = user_path_parent(dfd, pathname, &nd, &name); |
2263 | if(IS_ERR(name)) | ||
2264 | return PTR_ERR(name); | ||
2265 | |||
2266 | error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd); | ||
2267 | if (error) | 2178 | if (error) |
2268 | goto exit; | 2179 | return error; |
2269 | 2180 | ||
2270 | switch(nd.last_type) { | 2181 | switch(nd.last_type) { |
2271 | case LAST_DOTDOT: | 2182 | case LAST_DOTDOT: |
@@ -2294,7 +2205,6 @@ exit2: | |||
2294 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2205 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2295 | exit1: | 2206 | exit1: |
2296 | path_put(&nd.path); | 2207 | path_put(&nd.path); |
2297 | exit: | ||
2298 | putname(name); | 2208 | putname(name); |
2299 | return error; | 2209 | return error; |
2300 | } | 2210 | } |
@@ -2343,19 +2253,16 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
2343 | */ | 2253 | */ |
2344 | static long do_unlinkat(int dfd, const char __user *pathname) | 2254 | static long do_unlinkat(int dfd, const char __user *pathname) |
2345 | { | 2255 | { |
2346 | int error = 0; | 2256 | int error; |
2347 | char * name; | 2257 | char *name; |
2348 | struct dentry *dentry; | 2258 | struct dentry *dentry; |
2349 | struct nameidata nd; | 2259 | struct nameidata nd; |
2350 | struct inode *inode = NULL; | 2260 | struct inode *inode = NULL; |
2351 | 2261 | ||
2352 | name = getname(pathname); | 2262 | error = user_path_parent(dfd, pathname, &nd, &name); |
2353 | if(IS_ERR(name)) | ||
2354 | return PTR_ERR(name); | ||
2355 | |||
2356 | error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd); | ||
2357 | if (error) | 2263 | if (error) |
2358 | goto exit; | 2264 | return error; |
2265 | |||
2359 | error = -EISDIR; | 2266 | error = -EISDIR; |
2360 | if (nd.last_type != LAST_NORM) | 2267 | if (nd.last_type != LAST_NORM) |
2361 | goto exit1; | 2268 | goto exit1; |
@@ -2382,7 +2289,6 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
2382 | iput(inode); /* truncate the inode here */ | 2289 | iput(inode); /* truncate the inode here */ |
2383 | exit1: | 2290 | exit1: |
2384 | path_put(&nd.path); | 2291 | path_put(&nd.path); |
2385 | exit: | ||
2386 | putname(name); | 2292 | putname(name); |
2387 | return error; | 2293 | return error; |
2388 | 2294 | ||
@@ -2408,7 +2314,7 @@ asmlinkage long sys_unlink(const char __user *pathname) | |||
2408 | return do_unlinkat(AT_FDCWD, pathname); | 2314 | return do_unlinkat(AT_FDCWD, pathname); |
2409 | } | 2315 | } |
2410 | 2316 | ||
2411 | int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode) | 2317 | int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) |
2412 | { | 2318 | { |
2413 | int error = may_create(dir, dentry, NULL); | 2319 | int error = may_create(dir, dentry, NULL); |
2414 | 2320 | ||
@@ -2432,23 +2338,20 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, i | |||
2432 | asmlinkage long sys_symlinkat(const char __user *oldname, | 2338 | asmlinkage long sys_symlinkat(const char __user *oldname, |
2433 | int newdfd, const char __user *newname) | 2339 | int newdfd, const char __user *newname) |
2434 | { | 2340 | { |
2435 | int error = 0; | 2341 | int error; |
2436 | char * from; | 2342 | char *from; |
2437 | char * to; | 2343 | char *to; |
2438 | struct dentry *dentry; | 2344 | struct dentry *dentry; |
2439 | struct nameidata nd; | 2345 | struct nameidata nd; |
2440 | 2346 | ||
2441 | from = getname(oldname); | 2347 | from = getname(oldname); |
2442 | if(IS_ERR(from)) | 2348 | if (IS_ERR(from)) |
2443 | return PTR_ERR(from); | 2349 | return PTR_ERR(from); |
2444 | to = getname(newname); | ||
2445 | error = PTR_ERR(to); | ||
2446 | if (IS_ERR(to)) | ||
2447 | goto out_putname; | ||
2448 | 2350 | ||
2449 | error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); | 2351 | error = user_path_parent(newdfd, newname, &nd, &to); |
2450 | if (error) | 2352 | if (error) |
2451 | goto out; | 2353 | goto out_putname; |
2354 | |||
2452 | dentry = lookup_create(&nd, 0); | 2355 | dentry = lookup_create(&nd, 0); |
2453 | error = PTR_ERR(dentry); | 2356 | error = PTR_ERR(dentry); |
2454 | if (IS_ERR(dentry)) | 2357 | if (IS_ERR(dentry)) |
@@ -2457,14 +2360,13 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
2457 | error = mnt_want_write(nd.path.mnt); | 2360 | error = mnt_want_write(nd.path.mnt); |
2458 | if (error) | 2361 | if (error) |
2459 | goto out_dput; | 2362 | goto out_dput; |
2460 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO); | 2363 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); |
2461 | mnt_drop_write(nd.path.mnt); | 2364 | mnt_drop_write(nd.path.mnt); |
2462 | out_dput: | 2365 | out_dput: |
2463 | dput(dentry); | 2366 | dput(dentry); |
2464 | out_unlock: | 2367 | out_unlock: |
2465 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2368 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2466 | path_put(&nd.path); | 2369 | path_put(&nd.path); |
2467 | out: | ||
2468 | putname(to); | 2370 | putname(to); |
2469 | out_putname: | 2371 | out_putname: |
2470 | putname(from); | 2372 | putname(from); |
@@ -2498,19 +2400,19 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
2498 | return -EPERM; | 2400 | return -EPERM; |
2499 | if (!dir->i_op || !dir->i_op->link) | 2401 | if (!dir->i_op || !dir->i_op->link) |
2500 | return -EPERM; | 2402 | return -EPERM; |
2501 | if (S_ISDIR(old_dentry->d_inode->i_mode)) | 2403 | if (S_ISDIR(inode->i_mode)) |
2502 | return -EPERM; | 2404 | return -EPERM; |
2503 | 2405 | ||
2504 | error = security_inode_link(old_dentry, dir, new_dentry); | 2406 | error = security_inode_link(old_dentry, dir, new_dentry); |
2505 | if (error) | 2407 | if (error) |
2506 | return error; | 2408 | return error; |
2507 | 2409 | ||
2508 | mutex_lock(&old_dentry->d_inode->i_mutex); | 2410 | mutex_lock(&inode->i_mutex); |
2509 | DQUOT_INIT(dir); | 2411 | DQUOT_INIT(dir); |
2510 | error = dir->i_op->link(old_dentry, dir, new_dentry); | 2412 | error = dir->i_op->link(old_dentry, dir, new_dentry); |
2511 | mutex_unlock(&old_dentry->d_inode->i_mutex); | 2413 | mutex_unlock(&inode->i_mutex); |
2512 | if (!error) | 2414 | if (!error) |
2513 | fsnotify_link(dir, old_dentry->d_inode, new_dentry); | 2415 | fsnotify_link(dir, inode, new_dentry); |
2514 | return error; | 2416 | return error; |
2515 | } | 2417 | } |
2516 | 2418 | ||
@@ -2528,27 +2430,25 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
2528 | int flags) | 2430 | int flags) |
2529 | { | 2431 | { |
2530 | struct dentry *new_dentry; | 2432 | struct dentry *new_dentry; |
2531 | struct nameidata nd, old_nd; | 2433 | struct nameidata nd; |
2434 | struct path old_path; | ||
2532 | int error; | 2435 | int error; |
2533 | char * to; | 2436 | char *to; |
2534 | 2437 | ||
2535 | if ((flags & ~AT_SYMLINK_FOLLOW) != 0) | 2438 | if ((flags & ~AT_SYMLINK_FOLLOW) != 0) |
2536 | return -EINVAL; | 2439 | return -EINVAL; |
2537 | 2440 | ||
2538 | to = getname(newname); | 2441 | error = user_path_at(olddfd, oldname, |
2539 | if (IS_ERR(to)) | 2442 | flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0, |
2540 | return PTR_ERR(to); | 2443 | &old_path); |
2541 | |||
2542 | error = __user_walk_fd(olddfd, oldname, | ||
2543 | flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0, | ||
2544 | &old_nd); | ||
2545 | if (error) | 2444 | if (error) |
2546 | goto exit; | 2445 | return error; |
2547 | error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); | 2446 | |
2447 | error = user_path_parent(newdfd, newname, &nd, &to); | ||
2548 | if (error) | 2448 | if (error) |
2549 | goto out; | 2449 | goto out; |
2550 | error = -EXDEV; | 2450 | error = -EXDEV; |
2551 | if (old_nd.path.mnt != nd.path.mnt) | 2451 | if (old_path.mnt != nd.path.mnt) |
2552 | goto out_release; | 2452 | goto out_release; |
2553 | new_dentry = lookup_create(&nd, 0); | 2453 | new_dentry = lookup_create(&nd, 0); |
2554 | error = PTR_ERR(new_dentry); | 2454 | error = PTR_ERR(new_dentry); |
@@ -2557,7 +2457,7 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
2557 | error = mnt_want_write(nd.path.mnt); | 2457 | error = mnt_want_write(nd.path.mnt); |
2558 | if (error) | 2458 | if (error) |
2559 | goto out_dput; | 2459 | goto out_dput; |
2560 | error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry); | 2460 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); |
2561 | mnt_drop_write(nd.path.mnt); | 2461 | mnt_drop_write(nd.path.mnt); |
2562 | out_dput: | 2462 | out_dput: |
2563 | dput(new_dentry); | 2463 | dput(new_dentry); |
@@ -2565,10 +2465,9 @@ out_unlock: | |||
2565 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2465 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2566 | out_release: | 2466 | out_release: |
2567 | path_put(&nd.path); | 2467 | path_put(&nd.path); |
2568 | out: | ||
2569 | path_put(&old_nd.path); | ||
2570 | exit: | ||
2571 | putname(to); | 2468 | putname(to); |
2469 | out: | ||
2470 | path_put(&old_path); | ||
2572 | 2471 | ||
2573 | return error; | 2472 | return error; |
2574 | } | 2473 | } |
@@ -2621,7 +2520,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, | |||
2621 | * we'll need to flip '..'. | 2520 | * we'll need to flip '..'. |
2622 | */ | 2521 | */ |
2623 | if (new_dir != old_dir) { | 2522 | if (new_dir != old_dir) { |
2624 | error = permission(old_dentry->d_inode, MAY_WRITE, NULL); | 2523 | error = inode_permission(old_dentry->d_inode, MAY_WRITE); |
2625 | if (error) | 2524 | if (error) |
2626 | return error; | 2525 | return error; |
2627 | } | 2526 | } |
@@ -2724,20 +2623,22 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2724 | return error; | 2623 | return error; |
2725 | } | 2624 | } |
2726 | 2625 | ||
2727 | static int do_rename(int olddfd, const char *oldname, | 2626 | asmlinkage long sys_renameat(int olddfd, const char __user *oldname, |
2728 | int newdfd, const char *newname) | 2627 | int newdfd, const char __user *newname) |
2729 | { | 2628 | { |
2730 | int error = 0; | 2629 | struct dentry *old_dir, *new_dir; |
2731 | struct dentry * old_dir, * new_dir; | 2630 | struct dentry *old_dentry, *new_dentry; |
2732 | struct dentry * old_dentry, *new_dentry; | 2631 | struct dentry *trap; |
2733 | struct dentry * trap; | ||
2734 | struct nameidata oldnd, newnd; | 2632 | struct nameidata oldnd, newnd; |
2633 | char *from; | ||
2634 | char *to; | ||
2635 | int error; | ||
2735 | 2636 | ||
2736 | error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd); | 2637 | error = user_path_parent(olddfd, oldname, &oldnd, &from); |
2737 | if (error) | 2638 | if (error) |
2738 | goto exit; | 2639 | goto exit; |
2739 | 2640 | ||
2740 | error = do_path_lookup(newdfd, newname, LOOKUP_PARENT, &newnd); | 2641 | error = user_path_parent(newdfd, newname, &newnd, &to); |
2741 | if (error) | 2642 | if (error) |
2742 | goto exit1; | 2643 | goto exit1; |
2743 | 2644 | ||
@@ -2799,29 +2700,11 @@ exit3: | |||
2799 | unlock_rename(new_dir, old_dir); | 2700 | unlock_rename(new_dir, old_dir); |
2800 | exit2: | 2701 | exit2: |
2801 | path_put(&newnd.path); | 2702 | path_put(&newnd.path); |
2703 | putname(to); | ||
2802 | exit1: | 2704 | exit1: |
2803 | path_put(&oldnd.path); | 2705 | path_put(&oldnd.path); |
2804 | exit: | ||
2805 | return error; | ||
2806 | } | ||
2807 | |||
2808 | asmlinkage long sys_renameat(int olddfd, const char __user *oldname, | ||
2809 | int newdfd, const char __user *newname) | ||
2810 | { | ||
2811 | int error; | ||
2812 | char * from; | ||
2813 | char * to; | ||
2814 | |||
2815 | from = getname(oldname); | ||
2816 | if(IS_ERR(from)) | ||
2817 | return PTR_ERR(from); | ||
2818 | to = getname(newname); | ||
2819 | error = PTR_ERR(to); | ||
2820 | if (!IS_ERR(to)) { | ||
2821 | error = do_rename(olddfd, from, newdfd, to); | ||
2822 | putname(to); | ||
2823 | } | ||
2824 | putname(from); | 2706 | putname(from); |
2707 | exit: | ||
2825 | return error; | 2708 | return error; |
2826 | } | 2709 | } |
2827 | 2710 | ||
@@ -2959,8 +2842,7 @@ const struct inode_operations page_symlink_inode_operations = { | |||
2959 | .put_link = page_put_link, | 2842 | .put_link = page_put_link, |
2960 | }; | 2843 | }; |
2961 | 2844 | ||
2962 | EXPORT_SYMBOL(__user_walk); | 2845 | EXPORT_SYMBOL(user_path_at); |
2963 | EXPORT_SYMBOL(__user_walk_fd); | ||
2964 | EXPORT_SYMBOL(follow_down); | 2846 | EXPORT_SYMBOL(follow_down); |
2965 | EXPORT_SYMBOL(follow_up); | 2847 | EXPORT_SYMBOL(follow_up); |
2966 | EXPORT_SYMBOL(get_write_access); /* binfmt_aout */ | 2848 | EXPORT_SYMBOL(get_write_access); /* binfmt_aout */ |
@@ -2975,7 +2857,7 @@ EXPORT_SYMBOL(page_symlink); | |||
2975 | EXPORT_SYMBOL(page_symlink_inode_operations); | 2857 | EXPORT_SYMBOL(page_symlink_inode_operations); |
2976 | EXPORT_SYMBOL(path_lookup); | 2858 | EXPORT_SYMBOL(path_lookup); |
2977 | EXPORT_SYMBOL(vfs_path_lookup); | 2859 | EXPORT_SYMBOL(vfs_path_lookup); |
2978 | EXPORT_SYMBOL(permission); | 2860 | EXPORT_SYMBOL(inode_permission); |
2979 | EXPORT_SYMBOL(vfs_permission); | 2861 | EXPORT_SYMBOL(vfs_permission); |
2980 | EXPORT_SYMBOL(file_permission); | 2862 | EXPORT_SYMBOL(file_permission); |
2981 | EXPORT_SYMBOL(unlock_rename); | 2863 | EXPORT_SYMBOL(unlock_rename); |