summaryrefslogtreecommitdiffstatshomepage
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/shm.c45
1 files changed, 21 insertions, 24 deletions
diff --git a/ipc/shm.c b/ipc/shm.c
index fefa00d310fb..d8a38b3be5dd 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1366,15 +1366,14 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
1366 struct shmid_kernel *shp; 1366 struct shmid_kernel *shp;
1367 unsigned long addr = (unsigned long)shmaddr; 1367 unsigned long addr = (unsigned long)shmaddr;
1368 unsigned long size; 1368 unsigned long size;
1369 struct file *file; 1369 struct file *file, *base;
1370 int err; 1370 int err;
1371 unsigned long flags = MAP_SHARED; 1371 unsigned long flags = MAP_SHARED;
1372 unsigned long prot; 1372 unsigned long prot;
1373 int acc_mode; 1373 int acc_mode;
1374 struct ipc_namespace *ns; 1374 struct ipc_namespace *ns;
1375 struct shm_file_data *sfd; 1375 struct shm_file_data *sfd;
1376 struct path path; 1376 int f_flags;
1377 fmode_t f_mode;
1378 unsigned long populate = 0; 1377 unsigned long populate = 0;
1379 1378
1380 err = -EINVAL; 1379 err = -EINVAL;
@@ -1407,11 +1406,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
1407 if (shmflg & SHM_RDONLY) { 1406 if (shmflg & SHM_RDONLY) {
1408 prot = PROT_READ; 1407 prot = PROT_READ;
1409 acc_mode = S_IRUGO; 1408 acc_mode = S_IRUGO;
1410 f_mode = FMODE_READ; 1409 f_flags = O_RDONLY;
1411 } else { 1410 } else {
1412 prot = PROT_READ | PROT_WRITE; 1411 prot = PROT_READ | PROT_WRITE;
1413 acc_mode = S_IRUGO | S_IWUGO; 1412 acc_mode = S_IRUGO | S_IWUGO;
1414 f_mode = FMODE_READ | FMODE_WRITE; 1413 f_flags = O_RDWR;
1415 } 1414 }
1416 if (shmflg & SHM_EXEC) { 1415 if (shmflg & SHM_EXEC) {
1417 prot |= PROT_EXEC; 1416 prot |= PROT_EXEC;
@@ -1447,46 +1446,44 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
1447 goto out_unlock; 1446 goto out_unlock;
1448 } 1447 }
1449 1448
1450 path = shp->shm_file->f_path; 1449 /*
1451 path_get(&path); 1450 * We need to take a reference to the real shm file to prevent the
1451 * pointer from becoming stale in cases where the lifetime of the outer
1452 * file extends beyond that of the shm segment. It's not usually
1453 * possible, but it can happen during remap_file_pages() emulation as
1454 * that unmaps the memory, then does ->mmap() via file reference only.
1455 * We'll deny the ->mmap() if the shm segment was since removed, but to
1456 * detect shm ID reuse we need to compare the file pointers.
1457 */
1458 base = get_file(shp->shm_file);
1452 shp->shm_nattch++; 1459 shp->shm_nattch++;
1453 size = i_size_read(d_inode(path.dentry)); 1460 size = i_size_read(file_inode(base));
1454 ipc_unlock_object(&shp->shm_perm); 1461 ipc_unlock_object(&shp->shm_perm);
1455 rcu_read_unlock(); 1462 rcu_read_unlock();
1456 1463
1457 err = -ENOMEM; 1464 err = -ENOMEM;
1458 sfd = kzalloc(sizeof(*sfd), GFP_KERNEL); 1465 sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
1459 if (!sfd) { 1466 if (!sfd) {
1460 path_put(&path); 1467 fput(base);
1461 goto out_nattch; 1468 goto out_nattch;
1462 } 1469 }
1463 1470
1464 file = alloc_file(&path, f_mode, 1471 file = alloc_file_clone(base, f_flags,
1465 is_file_hugepages(shp->shm_file) ? 1472 is_file_hugepages(base) ?
1466 &shm_file_operations_huge : 1473 &shm_file_operations_huge :
1467 &shm_file_operations); 1474 &shm_file_operations);
1468 err = PTR_ERR(file); 1475 err = PTR_ERR(file);
1469 if (IS_ERR(file)) { 1476 if (IS_ERR(file)) {
1470 kfree(sfd); 1477 kfree(sfd);
1471 path_put(&path); 1478 fput(base);
1472 goto out_nattch; 1479 goto out_nattch;
1473 } 1480 }
1474 1481
1475 file->private_data = sfd;
1476 file->f_mapping = shp->shm_file->f_mapping;
1477 sfd->id = shp->shm_perm.id; 1482 sfd->id = shp->shm_perm.id;
1478 sfd->ns = get_ipc_ns(ns); 1483 sfd->ns = get_ipc_ns(ns);
1479 /* 1484 sfd->file = base;
1480 * We need to take a reference to the real shm file to prevent the
1481 * pointer from becoming stale in cases where the lifetime of the outer
1482 * file extends beyond that of the shm segment. It's not usually
1483 * possible, but it can happen during remap_file_pages() emulation as
1484 * that unmaps the memory, then does ->mmap() via file reference only.
1485 * We'll deny the ->mmap() if the shm segment was since removed, but to
1486 * detect shm ID reuse we need to compare the file pointers.
1487 */
1488 sfd->file = get_file(shp->shm_file);
1489 sfd->vm_ops = NULL; 1485 sfd->vm_ops = NULL;
1486 file->private_data = sfd;
1490 1487
1491 err = security_mmap_file(file, prot, flags); 1488 err = security_mmap_file(file, prot, flags);
1492 if (err) 1489 if (err)