diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/exec.c | 16 | ||||
| -rw-r--r-- | fs/fuse/file.c | 12 | ||||
| -rw-r--r-- | fs/ubifs/dir.c | 54 |
3 files changed, 56 insertions, 26 deletions
| @@ -1135,13 +1135,6 @@ void setup_new_exec(struct linux_binprm * bprm) | |||
| 1135 | set_dumpable(current->mm, suid_dumpable); | 1135 | set_dumpable(current->mm, suid_dumpable); |
| 1136 | } | 1136 | } |
| 1137 | 1137 | ||
| 1138 | /* | ||
| 1139 | * Flush performance counters when crossing a | ||
| 1140 | * security domain: | ||
| 1141 | */ | ||
| 1142 | if (!get_dumpable(current->mm)) | ||
| 1143 | perf_event_exit_task(current); | ||
| 1144 | |||
| 1145 | /* An exec changes our domain. We are no longer part of the thread | 1138 | /* An exec changes our domain. We are no longer part of the thread |
| 1146 | group */ | 1139 | group */ |
| 1147 | 1140 | ||
| @@ -1205,6 +1198,15 @@ void install_exec_creds(struct linux_binprm *bprm) | |||
| 1205 | 1198 | ||
| 1206 | commit_creds(bprm->cred); | 1199 | commit_creds(bprm->cred); |
| 1207 | bprm->cred = NULL; | 1200 | bprm->cred = NULL; |
| 1201 | |||
| 1202 | /* | ||
| 1203 | * Disable monitoring for regular users | ||
| 1204 | * when executing setuid binaries. Must | ||
| 1205 | * wait until new credentials are committed | ||
| 1206 | * by commit_creds() above | ||
| 1207 | */ | ||
| 1208 | if (get_dumpable(current->mm) != SUID_DUMP_USER) | ||
| 1209 | perf_event_exit_task(current); | ||
| 1208 | /* | 1210 | /* |
| 1209 | * cred_guard_mutex must be held at least to this point to prevent | 1211 | * cred_guard_mutex must be held at least to this point to prevent |
| 1210 | * ptrace_attach() from altering our determination of the task's | 1212 | * ptrace_attach() from altering our determination of the task's |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index e570081f9f76..35f281033142 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -2470,13 +2470,16 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
| 2470 | .mode = mode | 2470 | .mode = mode |
| 2471 | }; | 2471 | }; |
| 2472 | int err; | 2472 | int err; |
| 2473 | bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) || | ||
| 2474 | (mode & FALLOC_FL_PUNCH_HOLE); | ||
| 2473 | 2475 | ||
| 2474 | if (fc->no_fallocate) | 2476 | if (fc->no_fallocate) |
| 2475 | return -EOPNOTSUPP; | 2477 | return -EOPNOTSUPP; |
| 2476 | 2478 | ||
| 2477 | if (mode & FALLOC_FL_PUNCH_HOLE) { | 2479 | if (lock_inode) { |
| 2478 | mutex_lock(&inode->i_mutex); | 2480 | mutex_lock(&inode->i_mutex); |
| 2479 | fuse_set_nowrite(inode); | 2481 | if (mode & FALLOC_FL_PUNCH_HOLE) |
| 2482 | fuse_set_nowrite(inode); | ||
| 2480 | } | 2483 | } |
| 2481 | 2484 | ||
| 2482 | req = fuse_get_req_nopages(fc); | 2485 | req = fuse_get_req_nopages(fc); |
| @@ -2511,8 +2514,9 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
| 2511 | fuse_invalidate_attr(inode); | 2514 | fuse_invalidate_attr(inode); |
| 2512 | 2515 | ||
| 2513 | out: | 2516 | out: |
| 2514 | if (mode & FALLOC_FL_PUNCH_HOLE) { | 2517 | if (lock_inode) { |
| 2515 | fuse_release_nowrite(inode); | 2518 | if (mode & FALLOC_FL_PUNCH_HOLE) |
| 2519 | fuse_release_nowrite(inode); | ||
| 2516 | mutex_unlock(&inode->i_mutex); | 2520 | mutex_unlock(&inode->i_mutex); |
| 2517 | } | 2521 | } |
| 2518 | 2522 | ||
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index de08c92f2e23..605af512aec2 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c | |||
| @@ -349,31 +349,50 @@ static unsigned int vfs_dent_type(uint8_t type) | |||
| 349 | static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | 349 | static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) |
| 350 | { | 350 | { |
| 351 | int err, over = 0; | 351 | int err, over = 0; |
| 352 | loff_t pos = file->f_pos; | ||
| 352 | struct qstr nm; | 353 | struct qstr nm; |
| 353 | union ubifs_key key; | 354 | union ubifs_key key; |
| 354 | struct ubifs_dent_node *dent; | 355 | struct ubifs_dent_node *dent; |
| 355 | struct inode *dir = file_inode(file); | 356 | struct inode *dir = file_inode(file); |
| 356 | struct ubifs_info *c = dir->i_sb->s_fs_info; | 357 | struct ubifs_info *c = dir->i_sb->s_fs_info; |
| 357 | 358 | ||
| 358 | dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); | 359 | dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, pos); |
| 359 | 360 | ||
| 360 | if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2) | 361 | if (pos > UBIFS_S_KEY_HASH_MASK || pos == 2) |
| 361 | /* | 362 | /* |
| 362 | * The directory was seek'ed to a senseless position or there | 363 | * The directory was seek'ed to a senseless position or there |
| 363 | * are no more entries. | 364 | * are no more entries. |
| 364 | */ | 365 | */ |
| 365 | return 0; | 366 | return 0; |
| 366 | 367 | ||
| 368 | if (file->f_version == 0) { | ||
| 369 | /* | ||
| 370 | * The file was seek'ed, which means that @file->private_data | ||
| 371 | * is now invalid. This may also be just the first | ||
| 372 | * 'ubifs_readdir()' invocation, in which case | ||
| 373 | * @file->private_data is NULL, and the below code is | ||
| 374 | * basically a no-op. | ||
| 375 | */ | ||
| 376 | kfree(file->private_data); | ||
| 377 | file->private_data = NULL; | ||
| 378 | } | ||
| 379 | |||
| 380 | /* | ||
| 381 | * 'generic_file_llseek()' unconditionally sets @file->f_version to | ||
| 382 | * zero, and we use this for detecting whether the file was seek'ed. | ||
| 383 | */ | ||
| 384 | file->f_version = 1; | ||
| 385 | |||
| 367 | /* File positions 0 and 1 correspond to "." and ".." */ | 386 | /* File positions 0 and 1 correspond to "." and ".." */ |
| 368 | if (file->f_pos == 0) { | 387 | if (pos == 0) { |
| 369 | ubifs_assert(!file->private_data); | 388 | ubifs_assert(!file->private_data); |
| 370 | over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR); | 389 | over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR); |
| 371 | if (over) | 390 | if (over) |
| 372 | return 0; | 391 | return 0; |
| 373 | file->f_pos = 1; | 392 | file->f_pos = pos = 1; |
| 374 | } | 393 | } |
| 375 | 394 | ||
| 376 | if (file->f_pos == 1) { | 395 | if (pos == 1) { |
| 377 | ubifs_assert(!file->private_data); | 396 | ubifs_assert(!file->private_data); |
| 378 | over = filldir(dirent, "..", 2, 1, | 397 | over = filldir(dirent, "..", 2, 1, |
| 379 | parent_ino(file->f_path.dentry), DT_DIR); | 398 | parent_ino(file->f_path.dentry), DT_DIR); |
| @@ -389,7 +408,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
| 389 | goto out; | 408 | goto out; |
| 390 | } | 409 | } |
| 391 | 410 | ||
| 392 | file->f_pos = key_hash_flash(c, &dent->key); | 411 | file->f_pos = pos = key_hash_flash(c, &dent->key); |
| 393 | file->private_data = dent; | 412 | file->private_data = dent; |
| 394 | } | 413 | } |
| 395 | 414 | ||
| @@ -397,17 +416,16 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
| 397 | if (!dent) { | 416 | if (!dent) { |
| 398 | /* | 417 | /* |
| 399 | * The directory was seek'ed to and is now readdir'ed. | 418 | * The directory was seek'ed to and is now readdir'ed. |
| 400 | * Find the entry corresponding to @file->f_pos or the | 419 | * Find the entry corresponding to @pos or the closest one. |
| 401 | * closest one. | ||
| 402 | */ | 420 | */ |
| 403 | dent_key_init_hash(c, &key, dir->i_ino, file->f_pos); | 421 | dent_key_init_hash(c, &key, dir->i_ino, pos); |
| 404 | nm.name = NULL; | 422 | nm.name = NULL; |
| 405 | dent = ubifs_tnc_next_ent(c, &key, &nm); | 423 | dent = ubifs_tnc_next_ent(c, &key, &nm); |
| 406 | if (IS_ERR(dent)) { | 424 | if (IS_ERR(dent)) { |
| 407 | err = PTR_ERR(dent); | 425 | err = PTR_ERR(dent); |
| 408 | goto out; | 426 | goto out; |
| 409 | } | 427 | } |
| 410 | file->f_pos = key_hash_flash(c, &dent->key); | 428 | file->f_pos = pos = key_hash_flash(c, &dent->key); |
| 411 | file->private_data = dent; | 429 | file->private_data = dent; |
| 412 | } | 430 | } |
| 413 | 431 | ||
| @@ -419,7 +437,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
| 419 | ubifs_inode(dir)->creat_sqnum); | 437 | ubifs_inode(dir)->creat_sqnum); |
| 420 | 438 | ||
| 421 | nm.len = le16_to_cpu(dent->nlen); | 439 | nm.len = le16_to_cpu(dent->nlen); |
| 422 | over = filldir(dirent, dent->name, nm.len, file->f_pos, | 440 | over = filldir(dirent, dent->name, nm.len, pos, |
| 423 | le64_to_cpu(dent->inum), | 441 | le64_to_cpu(dent->inum), |
| 424 | vfs_dent_type(dent->type)); | 442 | vfs_dent_type(dent->type)); |
| 425 | if (over) | 443 | if (over) |
| @@ -435,9 +453,17 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
| 435 | } | 453 | } |
| 436 | 454 | ||
| 437 | kfree(file->private_data); | 455 | kfree(file->private_data); |
| 438 | file->f_pos = key_hash_flash(c, &dent->key); | 456 | file->f_pos = pos = key_hash_flash(c, &dent->key); |
| 439 | file->private_data = dent; | 457 | file->private_data = dent; |
| 440 | cond_resched(); | 458 | cond_resched(); |
| 459 | |||
| 460 | if (file->f_version == 0) | ||
| 461 | /* | ||
| 462 | * The file was seek'ed meanwhile, lets return and start | ||
| 463 | * reading direntries from the new position on the next | ||
| 464 | * invocation. | ||
| 465 | */ | ||
| 466 | return 0; | ||
| 441 | } | 467 | } |
| 442 | 468 | ||
| 443 | out: | 469 | out: |
| @@ -448,15 +474,13 @@ out: | |||
| 448 | 474 | ||
| 449 | kfree(file->private_data); | 475 | kfree(file->private_data); |
| 450 | file->private_data = NULL; | 476 | file->private_data = NULL; |
| 477 | /* 2 is a special value indicating that there are no more direntries */ | ||
| 451 | file->f_pos = 2; | 478 | file->f_pos = 2; |
| 452 | return 0; | 479 | return 0; |
| 453 | } | 480 | } |
| 454 | 481 | ||
| 455 | /* If a directory is seeked, we have to free saved readdir() state */ | ||
| 456 | static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence) | 482 | static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence) |
| 457 | { | 483 | { |
| 458 | kfree(file->private_data); | ||
| 459 | file->private_data = NULL; | ||
| 460 | return generic_file_llseek(file, offset, whence); | 484 | return generic_file_llseek(file, offset, whence); |
| 461 | } | 485 | } |
| 462 | 486 | ||
