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