linux/block/ioctl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/capability.h>
   3#include <linux/compat.h>
   4#include <linux/blkdev.h>
   5#include <linux/export.h>
   6#include <linux/gfp.h>
   7#include <linux/blkpg.h>
   8#include <linux/hdreg.h>
   9#include <linux/backing-dev.h>
  10#include <linux/fs.h>
  11#include <linux/blktrace_api.h>
  12#include <linux/pr.h>
  13#include <linux/uaccess.h>
  14#include "blk.h"
  15
  16static int blkpg_do_ioctl(struct block_device *bdev,
  17                          struct blkpg_partition __user *upart, int op)
  18{
  19        struct gendisk *disk = bdev->bd_disk;
  20        struct blkpg_partition p;
  21        long long start, length;
  22
  23        if (!capable(CAP_SYS_ADMIN))
  24                return -EACCES;
  25        if (copy_from_user(&p, upart, sizeof(struct blkpg_partition)))
  26                return -EFAULT;
  27        if (bdev_is_partition(bdev))
  28                return -EINVAL;
  29
  30        if (p.pno <= 0)
  31                return -EINVAL;
  32
  33        if (op == BLKPG_DEL_PARTITION)
  34                return bdev_del_partition(disk, p.pno);
  35
  36        start = p.start >> SECTOR_SHIFT;
  37        length = p.length >> SECTOR_SHIFT;
  38
  39        switch (op) {
  40        case BLKPG_ADD_PARTITION:
  41                /* check if partition is aligned to blocksize */
  42                if (p.start & (bdev_logical_block_size(bdev) - 1))
  43                        return -EINVAL;
  44                return bdev_add_partition(disk, p.pno, start, length);
  45        case BLKPG_RESIZE_PARTITION:
  46                return bdev_resize_partition(disk, p.pno, start, length);
  47        default:
  48                return -EINVAL;
  49        }
  50}
  51
  52static int blkpg_ioctl(struct block_device *bdev,
  53                       struct blkpg_ioctl_arg __user *arg)
  54{
  55        struct blkpg_partition __user *udata;
  56        int op;
  57
  58        if (get_user(op, &arg->op) || get_user(udata, &arg->data))
  59                return -EFAULT;
  60
  61        return blkpg_do_ioctl(bdev, udata, op);
  62}
  63
  64#ifdef CONFIG_COMPAT
  65struct compat_blkpg_ioctl_arg {
  66        compat_int_t op;
  67        compat_int_t flags;
  68        compat_int_t datalen;
  69        compat_caddr_t data;
  70};
  71
  72static int compat_blkpg_ioctl(struct block_device *bdev,
  73                              struct compat_blkpg_ioctl_arg __user *arg)
  74{
  75        compat_caddr_t udata;
  76        int op;
  77
  78        if (get_user(op, &arg->op) || get_user(udata, &arg->data))
  79                return -EFAULT;
  80
  81        return blkpg_do_ioctl(bdev, compat_ptr(udata), op);
  82}
  83#endif
  84
  85static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
  86                unsigned long arg, unsigned long flags)
  87{
  88        uint64_t range[2];
  89        uint64_t start, len;
  90        struct request_queue *q = bdev_get_queue(bdev);
  91        struct inode *inode = bdev->bd_inode;
  92        int err;
  93
  94        if (!(mode & FMODE_WRITE))
  95                return -EBADF;
  96
  97        if (!blk_queue_discard(q))
  98                return -EOPNOTSUPP;
  99
 100        if (copy_from_user(range, (void __user *)arg, sizeof(range)))
 101                return -EFAULT;
 102
 103        start = range[0];
 104        len = range[1];
 105
 106        if (start & 511)
 107                return -EINVAL;
 108        if (len & 511)
 109                return -EINVAL;
 110
 111        if (start + len > bdev_nr_bytes(bdev))
 112                return -EINVAL;
 113
 114        filemap_invalidate_lock(inode->i_mapping);
 115        err = truncate_bdev_range(bdev, mode, start, start + len - 1);
 116        if (err)
 117                goto fail;
 118
 119        err = blkdev_issue_discard(bdev, start >> 9, len >> 9,
 120                                   GFP_KERNEL, flags);
 121
 122fail:
 123        filemap_invalidate_unlock(inode->i_mapping);
 124        return err;
 125}
 126
 127static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode,
 128                unsigned long arg)
 129{
 130        uint64_t range[2];
 131        uint64_t start, end, len;
 132        struct inode *inode = bdev->bd_inode;
 133        int err;
 134
 135        if (!(mode & FMODE_WRITE))
 136                return -EBADF;
 137
 138        if (copy_from_user(range, (void __user *)arg, sizeof(range)))
 139                return -EFAULT;
 140
 141        start = range[0];
 142        len = range[1];
 143        end = start + len - 1;
 144
 145        if (start & 511)
 146                return -EINVAL;
 147        if (len & 511)
 148                return -EINVAL;
 149        if (end >= (uint64_t)bdev_nr_bytes(bdev))
 150                return -EINVAL;
 151        if (end < start)
 152                return -EINVAL;
 153
 154        /* Invalidate the page cache, including dirty pages */
 155        filemap_invalidate_lock(inode->i_mapping);
 156        err = truncate_bdev_range(bdev, mode, start, end);
 157        if (err)
 158                goto fail;
 159
 160        err = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL,
 161                                   BLKDEV_ZERO_NOUNMAP);
 162
 163fail:
 164        filemap_invalidate_unlock(inode->i_mapping);
 165        return err;
 166}
 167
 168static int put_ushort(unsigned short __user *argp, unsigned short val)
 169{
 170        return put_user(val, argp);
 171}
 172
 173static int put_int(int __user *argp, int val)
 174{
 175        return put_user(val, argp);
 176}
 177
 178static int put_uint(unsigned int __user *argp, unsigned int val)
 179{
 180        return put_user(val, argp);
 181}
 182
 183static int put_long(long __user *argp, long val)
 184{
 185        return put_user(val, argp);
 186}
 187
 188static int put_ulong(unsigned long __user *argp, unsigned long val)
 189{
 190        return put_user(val, argp);
 191}
 192
 193static int put_u64(u64 __user *argp, u64 val)
 194{
 195        return put_user(val, argp);
 196}
 197
 198#ifdef CONFIG_COMPAT
 199static int compat_put_long(compat_long_t __user *argp, long val)
 200{
 201        return put_user(val, argp);
 202}
 203
 204static int compat_put_ulong(compat_ulong_t __user *argp, compat_ulong_t val)
 205{
 206        return put_user(val, argp);
 207}
 208#endif
 209
 210#ifdef CONFIG_COMPAT
 211/*
 212 * This is the equivalent of compat_ptr_ioctl(), to be used by block
 213 * drivers that implement only commands that are completely compatible
 214 * between 32-bit and 64-bit user space
 215 */
 216int blkdev_compat_ptr_ioctl(struct block_device *bdev, fmode_t mode,
 217                        unsigned cmd, unsigned long arg)
 218{
 219        struct gendisk *disk = bdev->bd_disk;
 220
 221        if (disk->fops->ioctl)
 222                return disk->fops->ioctl(bdev, mode, cmd,
 223                                         (unsigned long)compat_ptr(arg));
 224
 225        return -ENOIOCTLCMD;
 226}
 227EXPORT_SYMBOL(blkdev_compat_ptr_ioctl);
 228#endif
 229
 230static int blkdev_pr_register(struct block_device *bdev,
 231                struct pr_registration __user *arg)
 232{
 233        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
 234        struct pr_registration reg;
 235
 236        if (!capable(CAP_SYS_ADMIN))
 237                return -EPERM;
 238        if (!ops || !ops->pr_register)
 239                return -EOPNOTSUPP;
 240        if (copy_from_user(&reg, arg, sizeof(reg)))
 241                return -EFAULT;
 242
 243        if (reg.flags & ~PR_FL_IGNORE_KEY)
 244                return -EOPNOTSUPP;
 245        return ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags);
 246}
 247
 248static int blkdev_pr_reserve(struct block_device *bdev,
 249                struct pr_reservation __user *arg)
 250{
 251        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
 252        struct pr_reservation rsv;
 253
 254        if (!capable(CAP_SYS_ADMIN))
 255                return -EPERM;
 256        if (!ops || !ops->pr_reserve)
 257                return -EOPNOTSUPP;
 258        if (copy_from_user(&rsv, arg, sizeof(rsv)))
 259                return -EFAULT;
 260
 261        if (rsv.flags & ~PR_FL_IGNORE_KEY)
 262                return -EOPNOTSUPP;
 263        return ops->pr_reserve(bdev, rsv.key, rsv.type, rsv.flags);
 264}
 265
 266static int blkdev_pr_release(struct block_device *bdev,
 267                struct pr_reservation __user *arg)
 268{
 269        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
 270        struct pr_reservation rsv;
 271
 272        if (!capable(CAP_SYS_ADMIN))
 273                return -EPERM;
 274        if (!ops || !ops->pr_release)
 275                return -EOPNOTSUPP;
 276        if (copy_from_user(&rsv, arg, sizeof(rsv)))
 277                return -EFAULT;
 278
 279        if (rsv.flags)
 280                return -EOPNOTSUPP;
 281        return ops->pr_release(bdev, rsv.key, rsv.type);
 282}
 283
 284static int blkdev_pr_preempt(struct block_device *bdev,
 285                struct pr_preempt __user *arg, bool abort)
 286{
 287        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
 288        struct pr_preempt p;
 289
 290        if (!capable(CAP_SYS_ADMIN))
 291                return -EPERM;
 292        if (!ops || !ops->pr_preempt)
 293                return -EOPNOTSUPP;
 294        if (copy_from_user(&p, arg, sizeof(p)))
 295                return -EFAULT;
 296
 297        if (p.flags)
 298                return -EOPNOTSUPP;
 299        return ops->pr_preempt(bdev, p.old_key, p.new_key, p.type, abort);
 300}
 301
 302static int blkdev_pr_clear(struct block_device *bdev,
 303                struct pr_clear __user *arg)
 304{
 305        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
 306        struct pr_clear c;
 307
 308        if (!capable(CAP_SYS_ADMIN))
 309                return -EPERM;
 310        if (!ops || !ops->pr_clear)
 311                return -EOPNOTSUPP;
 312        if (copy_from_user(&c, arg, sizeof(c)))
 313                return -EFAULT;
 314
 315        if (c.flags)
 316                return -EOPNOTSUPP;
 317        return ops->pr_clear(bdev, c.key);
 318}
 319
 320static int blkdev_flushbuf(struct block_device *bdev, fmode_t mode,
 321                unsigned cmd, unsigned long arg)
 322{
 323        if (!capable(CAP_SYS_ADMIN))
 324                return -EACCES;
 325        fsync_bdev(bdev);
 326        invalidate_bdev(bdev);
 327        return 0;
 328}
 329
 330static int blkdev_roset(struct block_device *bdev, fmode_t mode,
 331                unsigned cmd, unsigned long arg)
 332{
 333        int ret, n;
 334
 335        if (!capable(CAP_SYS_ADMIN))
 336                return -EACCES;
 337
 338        if (get_user(n, (int __user *)arg))
 339                return -EFAULT;
 340        if (bdev->bd_disk->fops->set_read_only) {
 341                ret = bdev->bd_disk->fops->set_read_only(bdev, n);
 342                if (ret)
 343                        return ret;
 344        }
 345        bdev->bd_read_only = n;
 346        return 0;
 347}
 348
 349static int blkdev_getgeo(struct block_device *bdev,
 350                struct hd_geometry __user *argp)
 351{
 352        struct gendisk *disk = bdev->bd_disk;
 353        struct hd_geometry geo;
 354        int ret;
 355
 356        if (!argp)
 357                return -EINVAL;
 358        if (!disk->fops->getgeo)
 359                return -ENOTTY;
 360
 361        /*
 362         * We need to set the startsect first, the driver may
 363         * want to override it.
 364         */
 365        memset(&geo, 0, sizeof(geo));
 366        geo.start = get_start_sect(bdev);
 367        ret = disk->fops->getgeo(bdev, &geo);
 368        if (ret)
 369                return ret;
 370        if (copy_to_user(argp, &geo, sizeof(geo)))
 371                return -EFAULT;
 372        return 0;
 373}
 374
 375#ifdef CONFIG_COMPAT
 376struct compat_hd_geometry {
 377        unsigned char heads;
 378        unsigned char sectors;
 379        unsigned short cylinders;
 380        u32 start;
 381};
 382
 383static int compat_hdio_getgeo(struct block_device *bdev,
 384                              struct compat_hd_geometry __user *ugeo)
 385{
 386        struct gendisk *disk = bdev->bd_disk;
 387        struct hd_geometry geo;
 388        int ret;
 389
 390        if (!ugeo)
 391                return -EINVAL;
 392        if (!disk->fops->getgeo)
 393                return -ENOTTY;
 394
 395        memset(&geo, 0, sizeof(geo));
 396        /*
 397         * We need to set the startsect first, the driver may
 398         * want to override it.
 399         */
 400        geo.start = get_start_sect(bdev);
 401        ret = disk->fops->getgeo(bdev, &geo);
 402        if (ret)
 403                return ret;
 404
 405        ret = copy_to_user(ugeo, &geo, 4);
 406        ret |= put_user(geo.start, &ugeo->start);
 407        if (ret)
 408                ret = -EFAULT;
 409
 410        return ret;
 411}
 412#endif
 413
 414/* set the logical block size */
 415static int blkdev_bszset(struct block_device *bdev, fmode_t mode,
 416                int __user *argp)
 417{
 418        int ret, n;
 419
 420        if (!capable(CAP_SYS_ADMIN))
 421                return -EACCES;
 422        if (!argp)
 423                return -EINVAL;
 424        if (get_user(n, argp))
 425                return -EFAULT;
 426
 427        if (mode & FMODE_EXCL)
 428                return set_blocksize(bdev, n);
 429
 430        if (IS_ERR(blkdev_get_by_dev(bdev->bd_dev, mode | FMODE_EXCL, &bdev)))
 431                return -EBUSY;
 432        ret = set_blocksize(bdev, n);
 433        blkdev_put(bdev, mode | FMODE_EXCL);
 434
 435        return ret;
 436}
 437
 438/*
 439 * Common commands that are handled the same way on native and compat
 440 * user space. Note the separate arg/argp parameters that are needed
 441 * to deal with the compat_ptr() conversion.
 442 */
 443static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode,
 444                                unsigned cmd, unsigned long arg, void __user *argp)
 445{
 446        unsigned int max_sectors;
 447
 448        switch (cmd) {
 449        case BLKFLSBUF:
 450                return blkdev_flushbuf(bdev, mode, cmd, arg);
 451        case BLKROSET:
 452                return blkdev_roset(bdev, mode, cmd, arg);
 453        case BLKDISCARD:
 454                return blk_ioctl_discard(bdev, mode, arg, 0);
 455        case BLKSECDISCARD:
 456                return blk_ioctl_discard(bdev, mode, arg,
 457                                BLKDEV_DISCARD_SECURE);
 458        case BLKZEROOUT:
 459                return blk_ioctl_zeroout(bdev, mode, arg);
 460        case BLKGETDISKSEQ:
 461                return put_u64(argp, bdev->bd_disk->diskseq);
 462        case BLKREPORTZONE:
 463                return blkdev_report_zones_ioctl(bdev, mode, cmd, arg);
 464        case BLKRESETZONE:
 465        case BLKOPENZONE:
 466        case BLKCLOSEZONE:
 467        case BLKFINISHZONE:
 468                return blkdev_zone_mgmt_ioctl(bdev, mode, cmd, arg);
 469        case BLKGETZONESZ:
 470                return put_uint(argp, bdev_zone_sectors(bdev));
 471        case BLKGETNRZONES:
 472                return put_uint(argp, blkdev_nr_zones(bdev->bd_disk));
 473        case BLKROGET:
 474                return put_int(argp, bdev_read_only(bdev) != 0);
 475        case BLKSSZGET: /* get block device logical block size */
 476                return put_int(argp, bdev_logical_block_size(bdev));
 477        case BLKPBSZGET: /* get block device physical block size */
 478                return put_uint(argp, bdev_physical_block_size(bdev));
 479        case BLKIOMIN:
 480                return put_uint(argp, bdev_io_min(bdev));
 481        case BLKIOOPT:
 482                return put_uint(argp, bdev_io_opt(bdev));
 483        case BLKALIGNOFF:
 484                return put_int(argp, bdev_alignment_offset(bdev));
 485        case BLKDISCARDZEROES:
 486                return put_uint(argp, 0);
 487        case BLKSECTGET:
 488                max_sectors = min_t(unsigned int, USHRT_MAX,
 489                                    queue_max_sectors(bdev_get_queue(bdev)));
 490                return put_ushort(argp, max_sectors);
 491        case BLKROTATIONAL:
 492                return put_ushort(argp, !blk_queue_nonrot(bdev_get_queue(bdev)));
 493        case BLKRASET:
 494        case BLKFRASET:
 495                if(!capable(CAP_SYS_ADMIN))
 496                        return -EACCES;
 497                bdev->bd_disk->bdi->ra_pages = (arg * 512) / PAGE_SIZE;
 498                return 0;
 499        case BLKRRPART:
 500                if (!capable(CAP_SYS_ADMIN))
 501                        return -EACCES;
 502                if (bdev_is_partition(bdev))
 503                        return -EINVAL;
 504                return disk_scan_partitions(bdev->bd_disk, mode & ~FMODE_EXCL);
 505        case BLKTRACESTART:
 506        case BLKTRACESTOP:
 507        case BLKTRACETEARDOWN:
 508                return blk_trace_ioctl(bdev, cmd, argp);
 509        case IOC_PR_REGISTER:
 510                return blkdev_pr_register(bdev, argp);
 511        case IOC_PR_RESERVE:
 512                return blkdev_pr_reserve(bdev, argp);
 513        case IOC_PR_RELEASE:
 514                return blkdev_pr_release(bdev, argp);
 515        case IOC_PR_PREEMPT:
 516                return blkdev_pr_preempt(bdev, argp, false);
 517        case IOC_PR_PREEMPT_ABORT:
 518                return blkdev_pr_preempt(bdev, argp, true);
 519        case IOC_PR_CLEAR:
 520                return blkdev_pr_clear(bdev, argp);
 521        default:
 522                return -ENOIOCTLCMD;
 523        }
 524}
 525
 526/*
 527 * Always keep this in sync with compat_blkdev_ioctl()
 528 * to handle all incompatible commands in both functions.
 529 *
 530 * New commands must be compatible and go into blkdev_common_ioctl
 531 */
 532long blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 533{
 534        struct block_device *bdev = I_BDEV(file->f_mapping->host);
 535        void __user *argp = (void __user *)arg;
 536        fmode_t mode = file->f_mode;
 537        int ret;
 538
 539        /*
 540         * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
 541         * to updated it before every ioctl.
 542         */
 543        if (file->f_flags & O_NDELAY)
 544                mode |= FMODE_NDELAY;
 545        else
 546                mode &= ~FMODE_NDELAY;
 547
 548        switch (cmd) {
 549        /* These need separate implementations for the data structure */
 550        case HDIO_GETGEO:
 551                return blkdev_getgeo(bdev, argp);
 552        case BLKPG:
 553                return blkpg_ioctl(bdev, argp);
 554
 555        /* Compat mode returns 32-bit data instead of 'long' */
 556        case BLKRAGET:
 557        case BLKFRAGET:
 558                if (!argp)
 559                        return -EINVAL;
 560                return put_long(argp,
 561                        (bdev->bd_disk->bdi->ra_pages * PAGE_SIZE) / 512);
 562        case BLKGETSIZE:
 563                if (bdev_nr_sectors(bdev) > ~0UL)
 564                        return -EFBIG;
 565                return put_ulong(argp, bdev_nr_sectors(bdev));
 566
 567        /* The data is compatible, but the command number is different */
 568        case BLKBSZGET: /* get block device soft block size (cf. BLKSSZGET) */
 569                return put_int(argp, block_size(bdev));
 570        case BLKBSZSET:
 571                return blkdev_bszset(bdev, mode, argp);
 572        case BLKGETSIZE64:
 573                return put_u64(argp, bdev_nr_bytes(bdev));
 574
 575        /* Incompatible alignment on i386 */
 576        case BLKTRACESETUP:
 577                return blk_trace_ioctl(bdev, cmd, argp);
 578        default:
 579                break;
 580        }
 581
 582        ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp);
 583        if (ret != -ENOIOCTLCMD)
 584                return ret;
 585
 586        if (!bdev->bd_disk->fops->ioctl)
 587                return -ENOTTY;
 588        return bdev->bd_disk->fops->ioctl(bdev, mode, cmd, arg);
 589}
 590
 591#ifdef CONFIG_COMPAT
 592
 593#define BLKBSZGET_32            _IOR(0x12, 112, int)
 594#define BLKBSZSET_32            _IOW(0x12, 113, int)
 595#define BLKGETSIZE64_32         _IOR(0x12, 114, int)
 596
 597/* Most of the generic ioctls are handled in the normal fallback path.
 598   This assumes the blkdev's low level compat_ioctl always returns
 599   ENOIOCTLCMD for unknown ioctls. */
 600long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 601{
 602        int ret;
 603        void __user *argp = compat_ptr(arg);
 604        struct block_device *bdev = I_BDEV(file->f_mapping->host);
 605        struct gendisk *disk = bdev->bd_disk;
 606        fmode_t mode = file->f_mode;
 607
 608        /*
 609         * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
 610         * to updated it before every ioctl.
 611         */
 612        if (file->f_flags & O_NDELAY)
 613                mode |= FMODE_NDELAY;
 614        else
 615                mode &= ~FMODE_NDELAY;
 616
 617        switch (cmd) {
 618        /* These need separate implementations for the data structure */
 619        case HDIO_GETGEO:
 620                return compat_hdio_getgeo(bdev, argp);
 621        case BLKPG:
 622                return compat_blkpg_ioctl(bdev, argp);
 623
 624        /* Compat mode returns 32-bit data instead of 'long' */
 625        case BLKRAGET:
 626        case BLKFRAGET:
 627                if (!argp)
 628                        return -EINVAL;
 629                return compat_put_long(argp,
 630                        (bdev->bd_disk->bdi->ra_pages * PAGE_SIZE) / 512);
 631        case BLKGETSIZE:
 632                if (bdev_nr_sectors(bdev) > ~0UL)
 633                        return -EFBIG;
 634                return compat_put_ulong(argp, bdev_nr_sectors(bdev));
 635
 636        /* The data is compatible, but the command number is different */
 637        case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
 638                return put_int(argp, bdev_logical_block_size(bdev));
 639        case BLKBSZSET_32:
 640                return blkdev_bszset(bdev, mode, argp);
 641        case BLKGETSIZE64_32:
 642                return put_u64(argp, bdev_nr_bytes(bdev));
 643
 644        /* Incompatible alignment on i386 */
 645        case BLKTRACESETUP32:
 646                return blk_trace_ioctl(bdev, cmd, argp);
 647        default:
 648                break;
 649        }
 650
 651        ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp);
 652        if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
 653                ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
 654
 655        return ret;
 656}
 657#endif
 658