Linux 3.2.2
This commit is contained in:
parent
8f7167dc29
commit
95885cbd27
|
@ -1,166 +0,0 @@
|
|||
From a7f3cbff409dde86b6bded8978f71bc193022427 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Date: Mon, 16 Jan 2012 17:12:58 +0100
|
||||
Subject: [PATCH 1/3] block: add and use scsi_blk_cmd_ioctl
|
||||
|
||||
Introduce a wrapper around scsi_cmd_ioctl that takes a block device.
|
||||
|
||||
The function will then be enhanced to detect partition block devices
|
||||
and, in that case, subject the ioctls to whitelisting.
|
||||
|
||||
[ Cherry picked from 6ad62f051ef784a48a6103af289f91b5c472e955 ]
|
||||
|
||||
Cc: stable@kernel.org
|
||||
Cc: linux-scsi@vger.kernel.org
|
||||
Cc: Jens Axboe <axboe@kernel.dk>
|
||||
Cc: James Bottomley <JBottomley@parallels.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
block/scsi_ioctl.c | 7 +++++++
|
||||
drivers/block/cciss.c | 6 +++---
|
||||
drivers/block/ub.c | 3 +--
|
||||
drivers/block/virtio_blk.c | 4 ++--
|
||||
drivers/cdrom/cdrom.c | 3 +--
|
||||
drivers/ide/ide-floppy_ioctl.c | 3 +--
|
||||
drivers/scsi/sd.c | 2 +-
|
||||
include/linux/blkdev.h | 2 ++
|
||||
8 files changed, 18 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
|
||||
index fbdf0d8..a2c11f3 100644
|
||||
--- a/block/scsi_ioctl.c
|
||||
+++ b/block/scsi_ioctl.c
|
||||
@@ -690,6 +690,13 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_cmd_ioctl);
|
||||
|
||||
+int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode,
|
||||
+ unsigned int cmd, void __user *arg)
|
||||
+{
|
||||
+ return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg);
|
||||
+}
|
||||
+EXPORT_SYMBOL(scsi_cmd_blk_ioctl);
|
||||
+
|
||||
static int __init blk_scsi_ioctl_init(void)
|
||||
{
|
||||
blk_set_cmd_filter_defaults(&blk_default_cmd_filter);
|
||||
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
|
||||
index 587cce5..b0f553b 100644
|
||||
--- a/drivers/block/cciss.c
|
||||
+++ b/drivers/block/cciss.c
|
||||
@@ -1735,7 +1735,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
case CCISS_BIG_PASSTHRU:
|
||||
return cciss_bigpassthru(h, argp);
|
||||
|
||||
- /* scsi_cmd_ioctl handles these, below, though some are not */
|
||||
+ /* scsi_cmd_blk_ioctl handles these, below, though some are not */
|
||||
/* very meaningful for cciss. SG_IO is the main one people want. */
|
||||
|
||||
case SG_GET_VERSION_NUM:
|
||||
@@ -1746,9 +1746,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
case SG_EMULATED_HOST:
|
||||
case SG_IO:
|
||||
case SCSI_IOCTL_SEND_COMMAND:
|
||||
- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
|
||||
+ return scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
|
||||
|
||||
- /* scsi_cmd_ioctl would normally handle these, below, but */
|
||||
+ /* scsi_cmd_blk_ioctl would normally handle these, below, but */
|
||||
/* they aren't a good fit for cciss, as CD-ROMs are */
|
||||
/* not supported, and we don't have any bus/target/lun */
|
||||
/* which we present to the kernel. */
|
||||
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
|
||||
index 0e376d4..7333b9e 100644
|
||||
--- a/drivers/block/ub.c
|
||||
+++ b/drivers/block/ub.c
|
||||
@@ -1744,12 +1744,11 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode)
|
||||
static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
- struct gendisk *disk = bdev->bd_disk;
|
||||
void __user *usermem = (void __user *) arg;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ub_mutex);
|
||||
- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem);
|
||||
+ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, usermem);
|
||||
mutex_unlock(&ub_mutex);
|
||||
|
||||
return ret;
|
||||
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
|
||||
index 4d0b70a..e46f2f7 100644
|
||||
--- a/drivers/block/virtio_blk.c
|
||||
+++ b/drivers/block/virtio_blk.c
|
||||
@@ -243,8 +243,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
|
||||
return -ENOTTY;
|
||||
|
||||
- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd,
|
||||
- (void __user *)data);
|
||||
+ return scsi_cmd_blk_ioctl(bdev, mode, cmd,
|
||||
+ (void __user *)data);
|
||||
}
|
||||
|
||||
/* We provide getgeo only to please some old bootloader/partitioning tools */
|
||||
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
|
||||
index f997c27..cedb231 100644
|
||||
--- a/drivers/cdrom/cdrom.c
|
||||
+++ b/drivers/cdrom/cdrom.c
|
||||
@@ -2747,12 +2747,11 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
|
||||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
int ret;
|
||||
- struct gendisk *disk = bdev->bd_disk;
|
||||
|
||||
/*
|
||||
* Try the generic SCSI command ioctl's first.
|
||||
*/
|
||||
- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
|
||||
+ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
|
||||
if (ret != -ENOTTY)
|
||||
return ret;
|
||||
|
||||
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
|
||||
index d267b7a..a22ca84 100644
|
||||
--- a/drivers/ide/ide-floppy_ioctl.c
|
||||
+++ b/drivers/ide/ide-floppy_ioctl.c
|
||||
@@ -292,8 +292,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
|
||||
* and CDROM_SEND_PACKET (legacy) ioctls
|
||||
*/
|
||||
if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
|
||||
- err = scsi_cmd_ioctl(bdev->bd_disk->queue, bdev->bd_disk,
|
||||
- mode, cmd, argp);
|
||||
+ err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
|
||||
|
||||
if (err == -ENOTTY)
|
||||
err = generic_ide_ioctl(drive, bdev, cmd, arg);
|
||||
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
|
||||
index fa3a591..ffa1c79 100644
|
||||
--- a/drivers/scsi/sd.c
|
||||
+++ b/drivers/scsi/sd.c
|
||||
@@ -1096,7 +1096,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
error = scsi_ioctl(sdp, cmd, p);
|
||||
break;
|
||||
default:
|
||||
- error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p);
|
||||
+ error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p);
|
||||
if (error != -ENOTTY)
|
||||
break;
|
||||
error = scsi_ioctl(sdp, cmd, p);
|
||||
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
|
||||
index 94acd81..ca7b869 100644
|
||||
--- a/include/linux/blkdev.h
|
||||
+++ b/include/linux/blkdev.h
|
||||
@@ -675,6 +675,8 @@ extern int blk_insert_cloned_request(struct request_queue *q,
|
||||
struct request *rq);
|
||||
extern void blk_delay_queue(struct request_queue *, unsigned long);
|
||||
extern void blk_recount_segments(struct request_queue *, struct bio *);
|
||||
+extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t,
|
||||
+ unsigned int, void __user *);
|
||||
extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
|
||||
unsigned int, void __user *);
|
||||
extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
|
||||
--
|
||||
1.7.7.6
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
From 51c6b870e10bbf60ee6a115216cfa7549addfce0 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Date: Mon, 16 Jan 2012 17:12:59 +0100
|
||||
Subject: [PATCH 2/3] block: fail SCSI passthrough ioctls on partition devices
|
||||
|
||||
Linux allows executing the SG_IO ioctl on a partition or LVM volume, and
|
||||
will pass the command to the underlying block device. This is
|
||||
well-known, but it is also a large security problem when (via Unix
|
||||
permissions, ACLs, SELinux or a combination thereof) a program or user
|
||||
needs to be granted access only to part of the disk.
|
||||
|
||||
This patch lets partitions forward a small set of harmless ioctls;
|
||||
others are logged with printk so that we can see which ioctls are
|
||||
actually sent. In my tests only CDROM_GET_CAPABILITY actually occurred.
|
||||
Of course it was being sent to a (partition on a) hard disk, so it would
|
||||
have failed with ENOTTY and the patch isn't changing anything in
|
||||
practice. Still, I'm treating it specially to avoid spamming the logs.
|
||||
|
||||
In principle, this restriction should include programs running with
|
||||
CAP_SYS_RAWIO. If for example I let a program access /dev/sda2 and
|
||||
/dev/sdb, it still should not be able to read/write outside the
|
||||
boundaries of /dev/sda2 independent of the capabilities. However, for
|
||||
now programs with CAP_SYS_RAWIO will still be allowed to send the
|
||||
ioctls. Their actions will still be logged.
|
||||
|
||||
This patch does not affect the non-libata IDE driver. That driver
|
||||
however already tests for bd != bd->bd_contains before issuing some
|
||||
ioctl; it could be restricted further to forbid these ioctls even for
|
||||
programs running with CAP_SYS_ADMIN/CAP_SYS_RAWIO.
|
||||
|
||||
[ Cherry picked from 3ed4e7ba4be8c72051d87dcb2dec279d97a18d41
|
||||
|
||||
Changes with respect to 3.3: return -ENOTTY from scsi_verify_blk_ioctl
|
||||
and -ENOIOCTLCMD from sd_compat_ioctl. ]
|
||||
|
||||
Cc: stable@kernel.org
|
||||
Cc: linux-scsi@vger.kernel.org
|
||||
Cc: Jens Axboe <axboe@kernel.dk>
|
||||
Cc: James Bottomley <JBottomley@parallels.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
[ Make it also print the command name when warning - Linus ]
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
block/scsi_ioctl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/scsi/sd.c | 11 +++++++++--
|
||||
include/linux/blkdev.h | 1 +
|
||||
3 files changed, 55 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
|
||||
index a2c11f3..688be8a 100644
|
||||
--- a/block/scsi_ioctl.c
|
||||
+++ b/block/scsi_ioctl.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/capability.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/cdrom.h>
|
||||
+#include <linux/ratelimit.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/times.h>
|
||||
#include <asm/uaccess.h>
|
||||
@@ -690,9 +691,53 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_cmd_ioctl);
|
||||
|
||||
+int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd)
|
||||
+{
|
||||
+ if (bd && bd == bd->bd_contains)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Actually none of these is particularly useful on a partition,
|
||||
+ * but they are safe.
|
||||
+ */
|
||||
+ switch (cmd) {
|
||||
+ case SCSI_IOCTL_GET_IDLUN:
|
||||
+ case SCSI_IOCTL_GET_BUS_NUMBER:
|
||||
+ case SCSI_IOCTL_GET_PCI:
|
||||
+ case SCSI_IOCTL_PROBE_HOST:
|
||||
+ case SG_GET_VERSION_NUM:
|
||||
+ case SG_SET_TIMEOUT:
|
||||
+ case SG_GET_TIMEOUT:
|
||||
+ case SG_GET_RESERVED_SIZE:
|
||||
+ case SG_SET_RESERVED_SIZE:
|
||||
+ case SG_EMULATED_HOST:
|
||||
+ return 0;
|
||||
+ case CDROM_GET_CAPABILITY:
|
||||
+ /* Keep this until we remove the printk below. udev sends it
|
||||
+ * and we do not want to spam dmesg about it. CD-ROMs do
|
||||
+ * not have partitions, so we get here only for disks.
|
||||
+ */
|
||||
+ return -ENOTTY;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* In particular, rule out all resets and host-specific ioctls. */
|
||||
+ printk_ratelimited(KERN_WARNING
|
||||
+ "%s: sending ioctl %x to a partition!\n", current->comm, cmd);
|
||||
+
|
||||
+ return capable(CAP_SYS_RAWIO) ? 0 : -ENOTTY;
|
||||
+}
|
||||
+EXPORT_SYMBOL(scsi_verify_blk_ioctl);
|
||||
+
|
||||
int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode,
|
||||
unsigned int cmd, void __user *arg)
|
||||
{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = scsi_verify_blk_ioctl(bd, cmd);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_cmd_blk_ioctl);
|
||||
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
|
||||
index ffa1c79..4b63c73 100644
|
||||
--- a/drivers/scsi/sd.c
|
||||
+++ b/drivers/scsi/sd.c
|
||||
@@ -1074,6 +1074,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
|
||||
"cmd=0x%x\n", disk->disk_name, cmd));
|
||||
|
||||
+ error = scsi_verify_blk_ioctl(bdev, cmd);
|
||||
+ if (error < 0)
|
||||
+ return error;
|
||||
+
|
||||
/*
|
||||
* If we are in the middle of error recovery, don't let anyone
|
||||
* else try and use this device. Also, if error recovery fails, it
|
||||
@@ -1266,6 +1270,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = scsi_verify_blk_ioctl(bdev, cmd);
|
||||
+ if (ret < 0)
|
||||
+ return -ENOIOCTLCMD;
|
||||
|
||||
/*
|
||||
* If we are in the middle of error recovery, don't let anyone
|
||||
@@ -1277,8 +1286,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
return -ENODEV;
|
||||
|
||||
if (sdev->host->hostt->compat_ioctl) {
|
||||
- int ret;
|
||||
-
|
||||
ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
|
||||
|
||||
return ret;
|
||||
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
|
||||
index ca7b869..0ed1eb0 100644
|
||||
--- a/include/linux/blkdev.h
|
||||
+++ b/include/linux/blkdev.h
|
||||
@@ -675,6 +675,7 @@ extern int blk_insert_cloned_request(struct request_queue *q,
|
||||
struct request *rq);
|
||||
extern void blk_delay_queue(struct request_queue *, unsigned long);
|
||||
extern void blk_recount_segments(struct request_queue *, struct bio *);
|
||||
+extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int);
|
||||
extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t,
|
||||
unsigned int, void __user *);
|
||||
extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
|
||||
--
|
||||
1.7.7.6
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
From 0d18592f2fcd3891e5955362565ea12d0846bf9f Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Date: Mon, 16 Jan 2012 17:13:00 +0100
|
||||
Subject: [PATCH 3/3] dm: do not forward ioctls from logical volumes to the
|
||||
underlying device
|
||||
|
||||
A logical volume can map to just part of underlying physical volume.
|
||||
In this case, it must be treated like a partition.
|
||||
|
||||
Based on a patch from Alasdair G Kergon.
|
||||
|
||||
[ Cherry picked from 95113a17a2a1eb06151dc698dca9bcc4a29e4fbb ]
|
||||
|
||||
Cc: stable@kernel.org
|
||||
Cc: Alasdair G Kergon <agk@redhat.com>
|
||||
Cc: dm-devel@redhat.com
|
||||
Cc: linux-scsi@vger.kernel.org
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
drivers/md/dm-flakey.c | 11 ++++++++++-
|
||||
drivers/md/dm-linear.c | 12 +++++++++++-
|
||||
drivers/md/dm-mpath.c | 6 ++++++
|
||||
3 files changed, 27 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
|
||||
index f84c080..9fb18c1 100644
|
||||
--- a/drivers/md/dm-flakey.c
|
||||
+++ b/drivers/md/dm-flakey.c
|
||||
@@ -368,8 +368,17 @@ static int flakey_status(struct dm_target *ti, status_type_t type,
|
||||
static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct flakey_c *fc = ti->private;
|
||||
+ struct dm_dev *dev = fc->dev;
|
||||
+ int r = 0;
|
||||
|
||||
- return __blkdev_driver_ioctl(fc->dev->bdev, fc->dev->mode, cmd, arg);
|
||||
+ /*
|
||||
+ * Only pass ioctls through if the device sizes match exactly.
|
||||
+ */
|
||||
+ if (fc->start ||
|
||||
+ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
|
||||
+ r = scsi_verify_blk_ioctl(NULL, cmd);
|
||||
+
|
||||
+ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
|
||||
}
|
||||
|
||||
static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
|
||||
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
|
||||
index 3921e3b..9728839 100644
|
||||
--- a/drivers/md/dm-linear.c
|
||||
+++ b/drivers/md/dm-linear.c
|
||||
@@ -116,7 +116,17 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct linear_c *lc = (struct linear_c *) ti->private;
|
||||
- return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg);
|
||||
+ struct dm_dev *dev = lc->dev;
|
||||
+ int r = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Only pass ioctls through if the device sizes match exactly.
|
||||
+ */
|
||||
+ if (lc->start ||
|
||||
+ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
|
||||
+ r = scsi_verify_blk_ioctl(NULL, cmd);
|
||||
+
|
||||
+ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
|
||||
}
|
||||
|
||||
static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
|
||||
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
|
||||
index 5e0090e..801d92d 100644
|
||||
--- a/drivers/md/dm-mpath.c
|
||||
+++ b/drivers/md/dm-mpath.c
|
||||
@@ -1520,6 +1520,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
|
||||
|
||||
spin_unlock_irqrestore(&m->lock, flags);
|
||||
|
||||
+ /*
|
||||
+ * Only pass ioctls through if the device sizes match exactly.
|
||||
+ */
|
||||
+ if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
|
||||
+ r = scsi_verify_blk_ioctl(NULL, cmd);
|
||||
+
|
||||
return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
|
||||
}
|
||||
|
||||
--
|
||||
1.7.7.6
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
From cced5041ed5a2d1352186510944b0ddfbdbe4c0b Mon Sep 17 00:00:00 2001
|
||||
From: Stratos Psomadakis <psomas@gentoo.org>
|
||||
Date: Sun, 4 Dec 2011 02:23:54 +0200
|
||||
Subject: [PATCH] [SCSI] sym53c8xx: Fix NULL pointer dereference in
|
||||
slave_destroy
|
||||
|
||||
sym53c8xx_slave_destroy unconditionally assumes that sym53c8xx_slave_alloc has
|
||||
succesesfully allocated a sym_lcb. This can lead to a NULL pointer dereference
|
||||
(exposed by commit 4e6c82b).
|
||||
|
||||
Signed-off-by: Stratos Psomadakis <psomas@gentoo.org>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
|
||||
---
|
||||
drivers/scsi/sym53c8xx_2/sym_glue.c | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
|
||||
index b4543f5..36d1ed7 100644
|
||||
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
|
||||
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
|
||||
@@ -839,6 +839,10 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev)
|
||||
struct sym_lcb *lp = sym_lp(tp, sdev->lun);
|
||||
unsigned long flags;
|
||||
|
||||
+ /* if slave_alloc returned before allocating a sym_lcb, return */
|
||||
+ if (!lp)
|
||||
+ return;
|
||||
+
|
||||
spin_lock_irqsave(np->s.host->host_lock, flags);
|
||||
|
||||
if (lp->busy_itlq || lp->busy_itl) {
|
||||
--
|
||||
1.7.7.5
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
From b2ccccdca46273c7b321ecf5041c362cd950da20 Mon Sep 17 00:00:00 2001
|
||||
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
||||
Date: Thu, 10 Nov 2011 06:55:04 -0800
|
||||
Subject: [PATCH] iwlagn: check for SMPS mode
|
||||
|
||||
Check and report WARN only when its invalid
|
||||
|
||||
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
||||
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
||||
---
|
||||
drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 1 +
|
||||
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 3 +++
|
||||
2 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
|
||||
index 1a52ed2..6465983 100644
|
||||
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
|
||||
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
|
||||
@@ -827,6 +827,7 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
|
||||
case IEEE80211_SMPS_STATIC:
|
||||
case IEEE80211_SMPS_DYNAMIC:
|
||||
return IWL_NUM_IDLE_CHAINS_SINGLE;
|
||||
+ case IEEE80211_SMPS_AUTOMATIC:
|
||||
case IEEE80211_SMPS_OFF:
|
||||
return active_cnt;
|
||||
default:
|
||||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
|
||||
index 4c52bee..8e45fba 100644
|
||||
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
|
||||
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
|
||||
@@ -542,6 +542,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
|
||||
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
+ goto out;
|
||||
+
|
||||
if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
|
||||
goto out;
|
||||
--
|
||||
1.7.7.5
|
||||
|
40
kernel.spec
40
kernel.spec
|
@ -54,7 +54,7 @@ Summary: The Linux kernel
|
|||
# For non-released -rc kernels, this will be appended after the rcX and
|
||||
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
|
||||
#
|
||||
%global baserelease 4
|
||||
%global baserelease 1
|
||||
%global fedora_build %{baserelease}
|
||||
|
||||
# base_sublevel is the kernel version we're starting with and patching
|
||||
|
@ -66,7 +66,7 @@ Summary: The Linux kernel
|
|||
%if 0%{?released_kernel}
|
||||
|
||||
# Do we have a -stable update to apply?
|
||||
%define stable_update 1
|
||||
%define stable_update 2
|
||||
# Is it a -stable RC?
|
||||
%define stable_rc 0
|
||||
# Set rpm version accordingly
|
||||
|
@ -782,10 +782,6 @@ Patch21074: KVM-x86-fix-missing-checks-in-syscall-emulation.patch
|
|||
#rhbz 728740
|
||||
Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch
|
||||
|
||||
Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch
|
||||
Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch
|
||||
Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch
|
||||
|
||||
#rhbz752176
|
||||
Patch21080: sysfs-msi-irq-per-device.patch
|
||||
|
||||
|
@ -794,9 +790,6 @@ Patch21082: procfs-parse-mount-options.patch
|
|||
Patch21083: procfs-add-hidepid-and-gid-mount-options.patch
|
||||
Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch
|
||||
|
||||
#rhbz 782681
|
||||
Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch
|
||||
|
||||
#rhbz 783211
|
||||
Patch21087: fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch
|
||||
|
||||
|
@ -806,21 +799,12 @@ Patch22100: msi-irq-sysfs-warning.patch
|
|||
# rhbz 754907
|
||||
Patch21101: hpsa-add-irqf-shared.patch
|
||||
|
||||
#rhbz 731365
|
||||
Patch21220: mac80211_offchannel_rework_revert.patch
|
||||
|
||||
Patch21225: pci-Rework-ASPM-disable-code.patch
|
||||
|
||||
Patch21226: pci-crs-blacklist.patch
|
||||
|
||||
Patch21227: mac80211-fix-work-removal-on-deauth-request.patch
|
||||
|
||||
#rhbz 781625
|
||||
Patch21228: SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch
|
||||
|
||||
#rhbz 766071
|
||||
Patch21229: iwlagn-check-for-SMPS-mode.patch
|
||||
|
||||
#rhbz 718790
|
||||
Patch21230: rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch
|
||||
|
||||
|
@ -1482,9 +1466,6 @@ ApplyPatch sysfs-msi-irq-per-device.patch
|
|||
# rhbz 754907
|
||||
ApplyPatch hpsa-add-irqf-shared.patch
|
||||
|
||||
#rhbz 731365
|
||||
ApplyPatch mac80211_offchannel_rework_revert.patch
|
||||
|
||||
ApplyPatch pci-Rework-ASPM-disable-code.patch
|
||||
|
||||
#ApplyPatch pci-crs-blacklist.patch
|
||||
|
@ -1512,27 +1493,13 @@ ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch
|
|||
#rhbz 728740
|
||||
ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch
|
||||
|
||||
#rhbz 769911
|
||||
ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch
|
||||
ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch
|
||||
ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch
|
||||
|
||||
#rhbz 782686
|
||||
ApplyPatch procfs-parse-mount-options.patch
|
||||
ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch
|
||||
ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch
|
||||
|
||||
#rhbz 782681
|
||||
ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch
|
||||
|
||||
ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch
|
||||
|
||||
#rhbz 781625
|
||||
ApplyPatch SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch
|
||||
|
||||
#rhbz 766071
|
||||
ApplyPatch iwlagn-check-for-SMPS-mode.patch
|
||||
|
||||
ApplyPatch rcu-reintroduce-missing-calls.patch
|
||||
|
||||
#rhbz 718790
|
||||
|
@ -2312,7 +2279,8 @@ fi
|
|||
# and build.
|
||||
|
||||
%changelog
|
||||
* Wed Jan 25 2012 Josh Boyer <jwboyer@redhat.com>
|
||||
* Wed Jan 25 2012 Josh Boyer <jwboyer@redhat.com> - 3.2.2-1
|
||||
- Linux 3.2.2
|
||||
- Add patch to invalidate parent cache when fsync is called on a partition
|
||||
(rhbz 783211)
|
||||
|
||||
|
|
|
@ -1,594 +0,0 @@
|
|||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
|
||||
index 9fab144..4f8cf7f 100644
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -694,6 +694,8 @@ struct tpt_led_trigger {
|
||||
* well be on the operating channel
|
||||
* @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to
|
||||
* determine if we are on the operating channel or not
|
||||
+ * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning,
|
||||
+ * gets only set in conjunction with SCAN_SW_SCANNING
|
||||
* @SCAN_COMPLETED: Set for our scan work function when the driver reported
|
||||
* that the scan completed.
|
||||
* @SCAN_ABORTED: Set for our scan work function when the driver reported
|
||||
@@ -702,6 +704,7 @@ struct tpt_led_trigger {
|
||||
enum {
|
||||
SCAN_SW_SCANNING,
|
||||
SCAN_HW_SCANNING,
|
||||
+ SCAN_OFF_CHANNEL,
|
||||
SCAN_COMPLETED,
|
||||
SCAN_ABORTED,
|
||||
};
|
||||
@@ -1197,14 +1200,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_sched_scan_stopped_work(struct work_struct *work);
|
||||
|
||||
/* off-channel helpers */
|
||||
-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local);
|
||||
-void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
|
||||
- bool tell_ap);
|
||||
-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
|
||||
- bool offchannel_ps_enable);
|
||||
+void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local);
|
||||
+void ieee80211_offchannel_stop_station(struct ieee80211_local *local);
|
||||
void ieee80211_offchannel_return(struct ieee80211_local *local,
|
||||
- bool enable_beaconing,
|
||||
- bool offchannel_ps_disable);
|
||||
+ bool enable_beaconing);
|
||||
void ieee80211_hw_roc_setup(struct ieee80211_local *local);
|
||||
|
||||
/* interface handling */
|
||||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
|
||||
index acb4423..2d607e5 100644
|
||||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
|
||||
ieee80211_configure_filter(local);
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Returns true if we are logically configured to be on
|
||||
- * the operating channel AND the hardware-conf is currently
|
||||
- * configured on the operating channel. Compares channel-type
|
||||
- * as well.
|
||||
- */
|
||||
-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
|
||||
-{
|
||||
- struct ieee80211_channel *chan, *scan_chan;
|
||||
- enum nl80211_channel_type channel_type;
|
||||
-
|
||||
- /* This logic needs to match logic in ieee80211_hw_config */
|
||||
- if (local->scan_channel) {
|
||||
- chan = local->scan_channel;
|
||||
- /* If scanning on oper channel, use whatever channel-type
|
||||
- * is currently in use.
|
||||
- */
|
||||
- if (chan == local->oper_channel)
|
||||
- channel_type = local->_oper_channel_type;
|
||||
- else
|
||||
- channel_type = NL80211_CHAN_NO_HT;
|
||||
- } else if (local->tmp_channel) {
|
||||
- chan = scan_chan = local->tmp_channel;
|
||||
- channel_type = local->tmp_channel_type;
|
||||
- } else {
|
||||
- chan = local->oper_channel;
|
||||
- channel_type = local->_oper_channel_type;
|
||||
- }
|
||||
-
|
||||
- if (chan != local->oper_channel ||
|
||||
- channel_type != local->_oper_channel_type)
|
||||
- return false;
|
||||
-
|
||||
- /* Check current hardware-config against oper_channel. */
|
||||
- if ((local->oper_channel != local->hw.conf.channel) ||
|
||||
- (local->_oper_channel_type != local->hw.conf.channel_type))
|
||||
- return false;
|
||||
-
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
|
||||
{
|
||||
struct ieee80211_channel *chan, *scan_chan;
|
||||
@@ -145,9 +104,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
|
||||
|
||||
scan_chan = local->scan_channel;
|
||||
|
||||
- /* If this off-channel logic ever changes, ieee80211_on_oper_channel
|
||||
- * may need to change as well.
|
||||
- */
|
||||
offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
|
||||
if (scan_chan) {
|
||||
chan = scan_chan;
|
||||
@@ -158,19 +114,17 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
|
||||
channel_type = local->_oper_channel_type;
|
||||
else
|
||||
channel_type = NL80211_CHAN_NO_HT;
|
||||
- } else if (local->tmp_channel) {
|
||||
+ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||
+ } else if (local->tmp_channel &&
|
||||
+ local->oper_channel != local->tmp_channel) {
|
||||
chan = scan_chan = local->tmp_channel;
|
||||
channel_type = local->tmp_channel_type;
|
||||
+ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||
} else {
|
||||
chan = local->oper_channel;
|
||||
channel_type = local->_oper_channel_type;
|
||||
- }
|
||||
-
|
||||
- if (chan != local->oper_channel ||
|
||||
- channel_type != local->_oper_channel_type)
|
||||
- local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||
- else
|
||||
local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
|
||||
+ }
|
||||
|
||||
offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
|
||||
|
||||
@@ -279,7 +233,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (local->quiescing || !ieee80211_sdata_running(sdata) ||
|
||||
- test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) {
|
||||
+ test_bit(SCAN_SW_SCANNING, &local->scanning)) {
|
||||
sdata->vif.bss_conf.enable_beacon = false;
|
||||
} else {
|
||||
/*
|
||||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
|
||||
index 13427b1..b4e5267 100644
|
||||
--- a/net/mac80211/offchannel.c
|
||||
+++ b/net/mac80211/offchannel.c
|
||||
@@ -17,14 +17,10 @@
|
||||
#include "driver-trace.h"
|
||||
|
||||
/*
|
||||
- * Tell our hardware to disable PS.
|
||||
- * Optionally inform AP that we will go to sleep so that it will buffer
|
||||
- * the frames while we are doing off-channel work. This is optional
|
||||
- * because we *may* be doing work on-operating channel, and want our
|
||||
- * hardware unconditionally awake, but still let the AP send us normal frames.
|
||||
+ * inform AP that we will go to sleep so that it will buffer the frames
|
||||
+ * while we scan
|
||||
*/
|
||||
-static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata,
|
||||
- bool tell_ap)
|
||||
+static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
@@ -45,8 +41,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
|
||||
}
|
||||
|
||||
- if (tell_ap && (!local->offchannel_ps_enabled ||
|
||||
- !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)))
|
||||
+ if (!(local->offchannel_ps_enabled) ||
|
||||
+ !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
|
||||
/*
|
||||
* If power save was enabled, no need to send a nullfunc
|
||||
* frame because AP knows that we are sleeping. But if the
|
||||
@@ -81,9 +77,6 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
|
||||
* we are sleeping, let's just enable power save mode in
|
||||
* hardware.
|
||||
*/
|
||||
- /* TODO: Only set hardware if CONF_PS changed?
|
||||
- * TODO: Should we set offchannel_ps_enabled to false?
|
||||
- */
|
||||
local->hw.conf.flags |= IEEE80211_CONF_PS;
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
|
||||
} else if (local->hw.conf.dynamic_ps_timeout > 0) {
|
||||
@@ -102,61 +95,63 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
|
||||
ieee80211_sta_reset_conn_monitor(sdata);
|
||||
}
|
||||
|
||||
-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
|
||||
- bool offchannel_ps_enable)
|
||||
+void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
- /*
|
||||
- * notify the AP about us leaving the channel and stop all
|
||||
- * STA interfaces.
|
||||
- */
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
- if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
|
||||
- set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
|
||||
-
|
||||
- /* Check to see if we should disable beaconing. */
|
||||
+ /* disable beaconing */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_ADHOC ||
|
||||
sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
|
||||
ieee80211_bss_info_change_notify(
|
||||
sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||
|
||||
- if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
|
||||
+ /*
|
||||
+ * only handle non-STA interfaces here, STA interfaces
|
||||
+ * are handled in ieee80211_offchannel_stop_station(),
|
||||
+ * e.g., from the background scan state machine.
|
||||
+ *
|
||||
+ * In addition, do not stop monitor interface to allow it to be
|
||||
+ * used from user space controlled off-channel operations.
|
||||
+ */
|
||||
+ if (sdata->vif.type != NL80211_IFTYPE_STATION &&
|
||||
+ sdata->vif.type != NL80211_IFTYPE_MONITOR) {
|
||||
+ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
|
||||
netif_tx_stop_all_queues(sdata->dev);
|
||||
- if (offchannel_ps_enable &&
|
||||
- (sdata->vif.type == NL80211_IFTYPE_STATION) &&
|
||||
- sdata->u.mgd.associated)
|
||||
- ieee80211_offchannel_ps_enable(sdata, true);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
||||
|
||||
-void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
|
||||
- bool tell_ap)
|
||||
+void ieee80211_offchannel_stop_station(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
+ /*
|
||||
+ * notify the AP about us leaving the channel and stop all STA interfaces
|
||||
+ */
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
- if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
- sdata->u.mgd.associated)
|
||||
- ieee80211_offchannel_ps_enable(sdata, tell_ap);
|
||||
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
+ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
|
||||
+ netif_tx_stop_all_queues(sdata->dev);
|
||||
+ if (sdata->u.mgd.associated)
|
||||
+ ieee80211_offchannel_ps_enable(sdata);
|
||||
+ }
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
||||
|
||||
void ieee80211_offchannel_return(struct ieee80211_local *local,
|
||||
- bool enable_beaconing,
|
||||
- bool offchannel_ps_disable)
|
||||
+ bool enable_beaconing)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
@@ -166,8 +161,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
|
||||
continue;
|
||||
|
||||
/* Tell AP we're back */
|
||||
- if (offchannel_ps_disable &&
|
||||
- sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
if (sdata->u.mgd.associated)
|
||||
ieee80211_offchannel_ps_disable(sdata);
|
||||
}
|
||||
@@ -187,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
|
||||
netif_tx_wake_all_queues(sdata->dev);
|
||||
}
|
||||
|
||||
- /* Check to see if we should re-enable beaconing */
|
||||
+ /* re-enable beaconing */
|
||||
if (enable_beaconing &&
|
||||
(sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_ADHOC ||
|
||||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
|
||||
index fe2c2a7..b46880e 100644
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -417,10 +417,16 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
|
||||
return RX_CONTINUE;
|
||||
|
||||
if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
|
||||
- test_bit(SCAN_SW_SCANNING, &local->scanning) ||
|
||||
local->sched_scanning)
|
||||
return ieee80211_scan_rx(rx->sdata, skb);
|
||||
|
||||
+ if (test_bit(SCAN_SW_SCANNING, &local->scanning)) {
|
||||
+ /* drop all the other packets during a software scan anyway */
|
||||
+ if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED)
|
||||
+ dev_kfree_skb(skb);
|
||||
+ return RX_QUEUED;
|
||||
+ }
|
||||
+
|
||||
/* scanning finished during invoking of handlers */
|
||||
I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
|
||||
return RX_DROP_UNUSABLE;
|
||||
@@ -2771,7 +2777,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||
local->dot11ReceivedFragmentCount++;
|
||||
|
||||
if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
|
||||
- test_bit(SCAN_SW_SCANNING, &local->scanning)))
|
||||
+ test_bit(SCAN_OFF_CHANNEL, &local->scanning)))
|
||||
status->rx_flags |= IEEE80211_RX_IN_SCAN;
|
||||
|
||||
if (ieee80211_is_mgmt(fc))
|
||||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
|
||||
index 6f09eca..2ba4977 100644
|
||||
--- a/net/mac80211/scan.c
|
||||
+++ b/net/mac80211/scan.c
|
||||
@@ -212,14 +212,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
|
||||
if (bss)
|
||||
ieee80211_rx_bss_put(sdata->local, bss);
|
||||
|
||||
- /* If we are on-operating-channel, and this packet is for the
|
||||
- * current channel, pass the pkt on up the stack so that
|
||||
- * the rest of the stack can make use of it.
|
||||
- */
|
||||
- if (ieee80211_cfg_on_oper_channel(sdata->local)
|
||||
- && (channel == sdata->local->oper_channel))
|
||||
- return RX_CONTINUE;
|
||||
-
|
||||
dev_kfree_skb(skb);
|
||||
return RX_QUEUED;
|
||||
}
|
||||
@@ -262,8 +254,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
|
||||
bool was_hw_scan)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
- bool on_oper_chan;
|
||||
- bool enable_beacons = false;
|
||||
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
@@ -296,25 +286,11 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
|
||||
local->scanning = 0;
|
||||
local->scan_channel = NULL;
|
||||
|
||||
- on_oper_chan = ieee80211_cfg_on_oper_channel(local);
|
||||
-
|
||||
- if (was_hw_scan || !on_oper_chan)
|
||||
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
- else
|
||||
- /* Set power back to normal operating levels. */
|
||||
- ieee80211_hw_config(local, 0);
|
||||
-
|
||||
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
if (!was_hw_scan) {
|
||||
- bool on_oper_chan2;
|
||||
ieee80211_configure_filter(local);
|
||||
drv_sw_scan_complete(local);
|
||||
- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
|
||||
- /* We should always be on-channel at this point. */
|
||||
- WARN_ON(!on_oper_chan2);
|
||||
- if (on_oper_chan2 && (on_oper_chan != on_oper_chan2))
|
||||
- enable_beacons = true;
|
||||
-
|
||||
- ieee80211_offchannel_return(local, enable_beacons, true);
|
||||
+ ieee80211_offchannel_return(local, true);
|
||||
}
|
||||
|
||||
ieee80211_recalc_idle(local);
|
||||
@@ -355,15 +331,13 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
|
||||
*/
|
||||
drv_sw_scan_start(local);
|
||||
|
||||
+ ieee80211_offchannel_stop_beaconing(local);
|
||||
+
|
||||
local->leave_oper_channel_time = 0;
|
||||
local->next_scan_state = SCAN_DECISION;
|
||||
local->scan_channel_idx = 0;
|
||||
|
||||
- /* We always want to use off-channel PS, even if we
|
||||
- * are not really leaving oper-channel. Don't
|
||||
- * tell the AP though, as long as we are on-channel.
|
||||
- */
|
||||
- ieee80211_offchannel_enable_all_ps(local, false);
|
||||
+ drv_flush(local, false);
|
||||
|
||||
ieee80211_configure_filter(local);
|
||||
|
||||
@@ -506,20 +480,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
|
||||
- next_chan = local->scan_req->channels[local->scan_channel_idx];
|
||||
-
|
||||
- if (ieee80211_cfg_on_oper_channel(local)) {
|
||||
- /* We're currently on operating channel. */
|
||||
- if (next_chan == local->oper_channel)
|
||||
- /* We don't need to move off of operating channel. */
|
||||
- local->next_scan_state = SCAN_SET_CHANNEL;
|
||||
- else
|
||||
- /*
|
||||
- * We do need to leave operating channel, as next
|
||||
- * scan is somewhere else.
|
||||
- */
|
||||
- local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
|
||||
- } else {
|
||||
+ if (local->scan_channel) {
|
||||
/*
|
||||
* we're currently scanning a different channel, let's
|
||||
* see if we can scan another channel without interfering
|
||||
@@ -535,6 +496,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
|
||||
*
|
||||
* Otherwise switch back to the operating channel.
|
||||
*/
|
||||
+ next_chan = local->scan_req->channels[local->scan_channel_idx];
|
||||
|
||||
bad_latency = time_after(jiffies +
|
||||
ieee80211_scan_get_channel_time(next_chan),
|
||||
@@ -552,6 +514,12 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
|
||||
local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
|
||||
else
|
||||
local->next_scan_state = SCAN_SET_CHANNEL;
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * we're on the operating channel currently, let's
|
||||
+ * leave that channel now to scan another one
|
||||
+ */
|
||||
+ local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
|
||||
}
|
||||
|
||||
*next_delay = 0;
|
||||
@@ -560,10 +528,9 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
|
||||
static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
|
||||
unsigned long *next_delay)
|
||||
{
|
||||
- /* PS will already be in off-channel mode,
|
||||
- * we do that once at the beginning of scanning.
|
||||
- */
|
||||
- ieee80211_offchannel_stop_vifs(local, false);
|
||||
+ ieee80211_offchannel_stop_station(local);
|
||||
+
|
||||
+ __set_bit(SCAN_OFF_CHANNEL, &local->scanning);
|
||||
|
||||
/*
|
||||
* What if the nullfunc frames didn't arrive?
|
||||
@@ -586,15 +553,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca
|
||||
{
|
||||
/* switch back to the operating channel */
|
||||
local->scan_channel = NULL;
|
||||
- if (!ieee80211_cfg_on_oper_channel(local))
|
||||
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
|
||||
/*
|
||||
- * Re-enable vifs and beaconing. Leave PS
|
||||
- * in off-channel state..will put that back
|
||||
- * on-channel at the end of scanning.
|
||||
+ * Only re-enable station mode interface now; beaconing will be
|
||||
+ * re-enabled once the full scan has been completed.
|
||||
*/
|
||||
- ieee80211_offchannel_return(local, true, false);
|
||||
+ ieee80211_offchannel_return(local, false);
|
||||
+
|
||||
+ __clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
|
||||
|
||||
*next_delay = HZ / 5;
|
||||
local->next_scan_state = SCAN_DECISION;
|
||||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
|
||||
index 8cb0d2d..54ea022 100644
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -258,8 +258,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
|
||||
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
|
||||
return TX_CONTINUE;
|
||||
|
||||
- if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
|
||||
- test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
|
||||
+ if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) &&
|
||||
!ieee80211_is_probe_req(hdr->frame_control) &&
|
||||
!ieee80211_is_nullfunc(hdr->frame_control))
|
||||
/*
|
||||
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
|
||||
index 7737f20..b76bf33 100644
|
||||
--- a/net/mac80211/work.c
|
||||
+++ b/net/mac80211/work.c
|
||||
@@ -901,26 +901,6 @@ static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct,
|
||||
return false;
|
||||
}
|
||||
|
||||
-static enum nl80211_channel_type
|
||||
-ieee80211_calc_ct(enum nl80211_channel_type wk_ct,
|
||||
- enum nl80211_channel_type oper_ct)
|
||||
-{
|
||||
- switch (wk_ct) {
|
||||
- case NL80211_CHAN_NO_HT:
|
||||
- return oper_ct;
|
||||
- case NL80211_CHAN_HT20:
|
||||
- if (oper_ct != NL80211_CHAN_NO_HT)
|
||||
- return oper_ct;
|
||||
- return wk_ct;
|
||||
- case NL80211_CHAN_HT40MINUS:
|
||||
- case NL80211_CHAN_HT40PLUS:
|
||||
- return wk_ct;
|
||||
- }
|
||||
- WARN_ON(1); /* shouldn't get here */
|
||||
- return wk_ct;
|
||||
-}
|
||||
-
|
||||
-
|
||||
static void ieee80211_work_timer(unsigned long data)
|
||||
{
|
||||
struct ieee80211_local *local = (void *) data;
|
||||
@@ -971,52 +951,18 @@ static void ieee80211_work_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
if (!started && !local->tmp_channel) {
|
||||
- bool on_oper_chan;
|
||||
- bool tmp_chan_changed = false;
|
||||
- bool on_oper_chan2;
|
||||
- enum nl80211_channel_type wk_ct;
|
||||
- on_oper_chan = ieee80211_cfg_on_oper_channel(local);
|
||||
-
|
||||
- /* Work with existing channel type if possible. */
|
||||
- wk_ct = wk->chan_type;
|
||||
- if (wk->chan == local->hw.conf.channel)
|
||||
- wk_ct = ieee80211_calc_ct(wk->chan_type,
|
||||
- local->hw.conf.channel_type);
|
||||
-
|
||||
- if (local->tmp_channel)
|
||||
- if ((local->tmp_channel != wk->chan) ||
|
||||
- (local->tmp_channel_type != wk_ct))
|
||||
- tmp_chan_changed = true;
|
||||
-
|
||||
- local->tmp_channel = wk->chan;
|
||||
- local->tmp_channel_type = wk_ct;
|
||||
/*
|
||||
- * Leave the station vifs in awake mode if they
|
||||
- * happen to be on the same channel as
|
||||
- * the requested channel.
|
||||
+ * TODO: could optimize this by leaving the
|
||||
+ * station vifs in awake mode if they
|
||||
+ * happen to be on the same channel as
|
||||
+ * the requested channel
|
||||
*/
|
||||
- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
|
||||
- if (on_oper_chan != on_oper_chan2) {
|
||||
- if (on_oper_chan2) {
|
||||
- /* going off oper channel, PS too */
|
||||
- ieee80211_offchannel_stop_vifs(local,
|
||||
- true);
|
||||
- ieee80211_hw_config(local, 0);
|
||||
- } else {
|
||||
- /* going on channel, but leave PS
|
||||
- * off-channel. */
|
||||
- ieee80211_hw_config(local, 0);
|
||||
- ieee80211_offchannel_return(local,
|
||||
- true,
|
||||
- false);
|
||||
- }
|
||||
- } else if (tmp_chan_changed)
|
||||
- /* Still off-channel, but on some other
|
||||
- * channel, so update hardware.
|
||||
- * PS should already be off-channel.
|
||||
- */
|
||||
- ieee80211_hw_config(local, 0);
|
||||
+ ieee80211_offchannel_stop_beaconing(local);
|
||||
+ ieee80211_offchannel_stop_station(local);
|
||||
|
||||
+ local->tmp_channel = wk->chan;
|
||||
+ local->tmp_channel_type = wk->chan_type;
|
||||
+ ieee80211_hw_config(local, 0);
|
||||
started = true;
|
||||
wk->timeout = jiffies;
|
||||
}
|
||||
@@ -1102,8 +1048,7 @@ static void ieee80211_work_work(struct work_struct *work)
|
||||
* we still need to do a hardware config. Currently,
|
||||
* we cannot be here while scanning, however.
|
||||
*/
|
||||
- if (!ieee80211_cfg_on_oper_channel(local))
|
||||
- ieee80211_hw_config(local, 0);
|
||||
+ ieee80211_hw_config(local, 0);
|
||||
|
||||
/* At the least, we need to disable offchannel_ps,
|
||||
* so just go ahead and run the entire offchannel
|
||||
@@ -1111,7 +1056,7 @@ static void ieee80211_work_work(struct work_struct *work)
|
||||
* beaconing if we were already on-oper-channel
|
||||
* as a future optimization.
|
||||
*/
|
||||
- ieee80211_offchannel_return(local, true, true);
|
||||
+ ieee80211_offchannel_return(local, true);
|
||||
|
||||
/* give connection some time to breathe */
|
||||
run_again(local, jiffies + HZ/2);
|
|
@ -1,268 +0,0 @@
|
|||
From e268337dfe26dfc7efd422a804dbb27977a3cccc Mon Sep 17 00:00:00 2001
|
||||
From: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Date: Tue, 17 Jan 2012 15:21:19 -0800
|
||||
Subject: [PATCH] proc: clean up and fix /proc/<pid>/mem handling
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Jüri Aedla reported that the /proc/<pid>/mem handling really isn't very
|
||||
robust, and it also doesn't match the permission checking of any of the
|
||||
other related files.
|
||||
|
||||
This changes it to do the permission checks at open time, and instead of
|
||||
tracking the process, it tracks the VM at the time of the open. That
|
||||
simplifies the code a lot, but does mean that if you hold the file
|
||||
descriptor open over an execve(), you'll continue to read from the _old_
|
||||
VM.
|
||||
|
||||
That is different from our previous behavior, but much simpler. If
|
||||
somebody actually finds a load where this matters, we'll need to revert
|
||||
this commit.
|
||||
|
||||
I suspect that nobody will ever notice - because the process mapping
|
||||
addresses will also have changed as part of the execve. So you cannot
|
||||
actually usefully access the fd across a VM change simply because all
|
||||
the offsets for IO would have changed too.
|
||||
|
||||
Reported-by: Jüri Aedla <asd@ut.ee>
|
||||
Cc: Al Viro <viro@zeniv.linux.org.uk>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
fs/proc/base.c | 145 +++++++++++++++-----------------------------------------
|
||||
1 files changed, 39 insertions(+), 106 deletions(-)
|
||||
|
||||
diff --git a/fs/proc/base.c b/fs/proc/base.c
|
||||
index 5485a53..662ddf2 100644
|
||||
--- a/fs/proc/base.c
|
||||
+++ b/fs/proc/base.c
|
||||
@@ -198,65 +198,7 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
|
||||
return result;
|
||||
}
|
||||
|
||||
-static struct mm_struct *__check_mem_permission(struct task_struct *task)
|
||||
-{
|
||||
- struct mm_struct *mm;
|
||||
-
|
||||
- mm = get_task_mm(task);
|
||||
- if (!mm)
|
||||
- return ERR_PTR(-EINVAL);
|
||||
-
|
||||
- /*
|
||||
- * A task can always look at itself, in case it chooses
|
||||
- * to use system calls instead of load instructions.
|
||||
- */
|
||||
- if (task == current)
|
||||
- return mm;
|
||||
-
|
||||
- /*
|
||||
- * If current is actively ptrace'ing, and would also be
|
||||
- * permitted to freshly attach with ptrace now, permit it.
|
||||
- */
|
||||
- if (task_is_stopped_or_traced(task)) {
|
||||
- int match;
|
||||
- rcu_read_lock();
|
||||
- match = (ptrace_parent(task) == current);
|
||||
- rcu_read_unlock();
|
||||
- if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
|
||||
- return mm;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * No one else is allowed.
|
||||
- */
|
||||
- mmput(mm);
|
||||
- return ERR_PTR(-EPERM);
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * If current may access user memory in @task return a reference to the
|
||||
- * corresponding mm, otherwise ERR_PTR.
|
||||
- */
|
||||
-static struct mm_struct *check_mem_permission(struct task_struct *task)
|
||||
-{
|
||||
- struct mm_struct *mm;
|
||||
- int err;
|
||||
-
|
||||
- /*
|
||||
- * Avoid racing if task exec's as we might get a new mm but validate
|
||||
- * against old credentials.
|
||||
- */
|
||||
- err = mutex_lock_killable(&task->signal->cred_guard_mutex);
|
||||
- if (err)
|
||||
- return ERR_PTR(err);
|
||||
-
|
||||
- mm = __check_mem_permission(task);
|
||||
- mutex_unlock(&task->signal->cred_guard_mutex);
|
||||
-
|
||||
- return mm;
|
||||
-}
|
||||
-
|
||||
-struct mm_struct *mm_for_maps(struct task_struct *task)
|
||||
+static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
|
||||
{
|
||||
struct mm_struct *mm;
|
||||
int err;
|
||||
@@ -267,7 +209,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
|
||||
|
||||
mm = get_task_mm(task);
|
||||
if (mm && mm != current->mm &&
|
||||
- !ptrace_may_access(task, PTRACE_MODE_READ)) {
|
||||
+ !ptrace_may_access(task, mode)) {
|
||||
mmput(mm);
|
||||
mm = ERR_PTR(-EACCES);
|
||||
}
|
||||
@@ -276,6 +218,11 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
|
||||
return mm;
|
||||
}
|
||||
|
||||
+struct mm_struct *mm_for_maps(struct task_struct *task)
|
||||
+{
|
||||
+ return mm_access(task, PTRACE_MODE_READ);
|
||||
+}
|
||||
+
|
||||
static int proc_pid_cmdline(struct task_struct *task, char * buffer)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -752,38 +699,39 @@ static const struct file_operations proc_single_file_operations = {
|
||||
|
||||
static int mem_open(struct inode* inode, struct file* file)
|
||||
{
|
||||
- file->private_data = (void*)((long)current->self_exec_id);
|
||||
+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
|
||||
+ struct mm_struct *mm;
|
||||
+
|
||||
+ if (!task)
|
||||
+ return -ESRCH;
|
||||
+
|
||||
+ mm = mm_access(task, PTRACE_MODE_ATTACH);
|
||||
+ put_task_struct(task);
|
||||
+
|
||||
+ if (IS_ERR(mm))
|
||||
+ return PTR_ERR(mm);
|
||||
+
|
||||
/* OK to pass negative loff_t, we can catch out-of-range */
|
||||
file->f_mode |= FMODE_UNSIGNED_OFFSET;
|
||||
+ file->private_data = mm;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t mem_read(struct file * file, char __user * buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
|
||||
+ int ret;
|
||||
char *page;
|
||||
unsigned long src = *ppos;
|
||||
- int ret = -ESRCH;
|
||||
- struct mm_struct *mm;
|
||||
+ struct mm_struct *mm = file->private_data;
|
||||
|
||||
- if (!task)
|
||||
- goto out_no_task;
|
||||
+ if (!mm)
|
||||
+ return 0;
|
||||
|
||||
- ret = -ENOMEM;
|
||||
page = (char *)__get_free_page(GFP_TEMPORARY);
|
||||
if (!page)
|
||||
- goto out;
|
||||
-
|
||||
- mm = check_mem_permission(task);
|
||||
- ret = PTR_ERR(mm);
|
||||
- if (IS_ERR(mm))
|
||||
- goto out_free;
|
||||
-
|
||||
- ret = -EIO;
|
||||
-
|
||||
- if (file->private_data != (void*)((long)current->self_exec_id))
|
||||
- goto out_put;
|
||||
+ return -ENOMEM;
|
||||
|
||||
ret = 0;
|
||||
|
||||
@@ -810,13 +758,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
|
||||
}
|
||||
*ppos = src;
|
||||
|
||||
-out_put:
|
||||
- mmput(mm);
|
||||
-out_free:
|
||||
free_page((unsigned long) page);
|
||||
-out:
|
||||
- put_task_struct(task);
|
||||
-out_no_task:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -825,27 +767,15 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
|
||||
{
|
||||
int copied;
|
||||
char *page;
|
||||
- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
|
||||
unsigned long dst = *ppos;
|
||||
- struct mm_struct *mm;
|
||||
+ struct mm_struct *mm = file->private_data;
|
||||
|
||||
- copied = -ESRCH;
|
||||
- if (!task)
|
||||
- goto out_no_task;
|
||||
+ if (!mm)
|
||||
+ return 0;
|
||||
|
||||
- copied = -ENOMEM;
|
||||
page = (char *)__get_free_page(GFP_TEMPORARY);
|
||||
if (!page)
|
||||
- goto out_task;
|
||||
-
|
||||
- mm = check_mem_permission(task);
|
||||
- copied = PTR_ERR(mm);
|
||||
- if (IS_ERR(mm))
|
||||
- goto out_free;
|
||||
-
|
||||
- copied = -EIO;
|
||||
- if (file->private_data != (void *)((long)current->self_exec_id))
|
||||
- goto out_mm;
|
||||
+ return -ENOMEM;
|
||||
|
||||
copied = 0;
|
||||
while (count > 0) {
|
||||
@@ -869,13 +799,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
|
||||
}
|
||||
*ppos = dst;
|
||||
|
||||
-out_mm:
|
||||
- mmput(mm);
|
||||
-out_free:
|
||||
free_page((unsigned long) page);
|
||||
-out_task:
|
||||
- put_task_struct(task);
|
||||
-out_no_task:
|
||||
return copied;
|
||||
}
|
||||
|
||||
@@ -895,11 +819,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig)
|
||||
return file->f_pos;
|
||||
}
|
||||
|
||||
+static int mem_release(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ struct mm_struct *mm = file->private_data;
|
||||
+
|
||||
+ mmput(mm);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct file_operations proc_mem_operations = {
|
||||
.llseek = mem_lseek,
|
||||
.read = mem_read,
|
||||
.write = mem_write,
|
||||
.open = mem_open,
|
||||
+ .release = mem_release,
|
||||
};
|
||||
|
||||
static ssize_t environ_read(struct file *file, char __user *buf,
|
||||
--
|
||||
1.7.7.5
|
||||
|
Loading…
Reference in New Issue