Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ublk: fix ublksrv pid handling for pid namespaces

When ublksrv runs inside a pid namespace, START/END_RECOVERY compared
the stored init-ns tgid against the userspace pid (getpid vnr), so the
check failed and control ops could not proceed. Compare against the
caller’s init-ns tgid and store that value, then translate it back to
the caller’s pid namespace when reporting GET_DEV_INFO so ublk list
shows a sensible pid.

Testing: start/recover in a pid namespace; `ublk list` shows
reasonable pid values in init, child, and sibling namespaces.

Fixes: c2c8089f325e ("ublk: validate ublk server pid")
Signed-off-by: Seamus Connor <sconnor@purestorage.com>
Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Seamus Connor and committed by
Jens Axboe
47bdf1d2 07a1bc5c

+34 -5
+34 -5
drivers/block/ublk_drv.c
··· 2885 2885 return ub; 2886 2886 } 2887 2887 2888 + static bool ublk_validate_user_pid(struct ublk_device *ub, pid_t ublksrv_pid) 2889 + { 2890 + rcu_read_lock(); 2891 + ublksrv_pid = pid_nr(find_vpid(ublksrv_pid)); 2892 + rcu_read_unlock(); 2893 + 2894 + return ub->ublksrv_tgid == ublksrv_pid; 2895 + } 2896 + 2888 2897 static int ublk_ctrl_start_dev(struct ublk_device *ub, 2889 2898 const struct ublksrv_ctrl_cmd *header) 2890 2899 { ··· 2962 2953 if (wait_for_completion_interruptible(&ub->completion) != 0) 2963 2954 return -EINTR; 2964 2955 2965 - if (ub->ublksrv_tgid != ublksrv_pid) 2956 + if (!ublk_validate_user_pid(ub, ublksrv_pid)) 2966 2957 return -EINVAL; 2967 2958 2968 2959 mutex_lock(&ub->mutex); ··· 2981 2972 disk->fops = &ub_fops; 2982 2973 disk->private_data = ub; 2983 2974 2984 - ub->dev_info.ublksrv_pid = ublksrv_pid; 2975 + ub->dev_info.ublksrv_pid = ub->ublksrv_tgid; 2985 2976 ub->ub_disk = disk; 2986 2977 2987 2978 ublk_apply_params(ub); ··· 3329 3320 static int ublk_ctrl_get_dev_info(struct ublk_device *ub, 3330 3321 const struct ublksrv_ctrl_cmd *header) 3331 3322 { 3323 + struct task_struct *p; 3324 + struct pid *pid; 3325 + struct ublksrv_ctrl_dev_info dev_info; 3326 + pid_t init_ublksrv_tgid = ub->dev_info.ublksrv_pid; 3332 3327 void __user *argp = (void __user *)(unsigned long)header->addr; 3333 3328 3334 3329 if (header->len < sizeof(struct ublksrv_ctrl_dev_info) || !header->addr) 3335 3330 return -EINVAL; 3336 3331 3337 - if (copy_to_user(argp, &ub->dev_info, sizeof(ub->dev_info))) 3332 + memcpy(&dev_info, &ub->dev_info, sizeof(dev_info)); 3333 + dev_info.ublksrv_pid = -1; 3334 + 3335 + if (init_ublksrv_tgid > 0) { 3336 + rcu_read_lock(); 3337 + pid = find_pid_ns(init_ublksrv_tgid, &init_pid_ns); 3338 + p = pid_task(pid, PIDTYPE_TGID); 3339 + if (p) { 3340 + int vnr = task_tgid_vnr(p); 3341 + 3342 + if (vnr) 3343 + dev_info.ublksrv_pid = vnr; 3344 + } 3345 + rcu_read_unlock(); 3346 + } 3347 + 3348 + if (copy_to_user(argp, &dev_info, sizeof(dev_info))) 3338 3349 return -EFAULT; 3339 3350 3340 3351 return 0; ··· 3499 3470 pr_devel("%s: All FETCH_REQs received, dev id %d\n", __func__, 3500 3471 header->dev_id); 3501 3472 3502 - if (ub->ublksrv_tgid != ublksrv_pid) 3473 + if (!ublk_validate_user_pid(ub, ublksrv_pid)) 3503 3474 return -EINVAL; 3504 3475 3505 3476 mutex_lock(&ub->mutex); ··· 3510 3481 ret = -EBUSY; 3511 3482 goto out_unlock; 3512 3483 } 3513 - ub->dev_info.ublksrv_pid = ublksrv_pid; 3484 + ub->dev_info.ublksrv_pid = ub->ublksrv_tgid; 3514 3485 ub->dev_info.state = UBLK_S_DEV_LIVE; 3515 3486 pr_devel("%s: new ublksrv_pid %d, dev id %d\n", 3516 3487 __func__, ublksrv_pid, header->dev_id);