mirror of https://gitee.com/openkylin/linux.git
f2fs: support FS_IOC_{GET,SET}FSLABEL
Support two generic fs ioctls FS_IOC_{GET,SET}FSLABEL, letting f2fs pass generic/492 testcase. Fixes were made by Eric where: - f2fs: fix buffer overruns in FS_IOC_{GET, SET}FSLABEL utf16s_to_utf8s() and utf8s_to_utf16s() take the number of characters, not the number of bytes. - f2fs: fix copying too many bytes in FS_IOC_SETFSLABEL Userspace provides a null-terminated string, so don't assume that the full FSLABEL_MAX bytes can always be copied. - f2fs: add missing authorization check in FS_IOC_SETFSLABEL FS_IOC_SETFSLABEL modifies the filesystem superblock, so it shouldn't be allowed to regular users. Require CAP_SYS_ADMIN, like xfs and btrfs do. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
899fee36fa
commit
4507847c86
|
@ -418,6 +418,9 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal,
|
||||||
#define F2FS_IOC_PRECACHE_EXTENTS _IO(F2FS_IOCTL_MAGIC, 15)
|
#define F2FS_IOC_PRECACHE_EXTENTS _IO(F2FS_IOCTL_MAGIC, 15)
|
||||||
#define F2FS_IOC_RESIZE_FS _IOW(F2FS_IOCTL_MAGIC, 16, __u64)
|
#define F2FS_IOC_RESIZE_FS _IOW(F2FS_IOCTL_MAGIC, 16, __u64)
|
||||||
|
|
||||||
|
#define F2FS_IOC_GET_VOLUME_NAME FS_IOC_GETFSLABEL
|
||||||
|
#define F2FS_IOC_SET_VOLUME_NAME FS_IOC_SETFSLABEL
|
||||||
|
|
||||||
#define F2FS_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY
|
#define F2FS_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY
|
||||||
#define F2FS_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY
|
#define F2FS_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY
|
||||||
#define F2FS_IOC_GET_ENCRYPTION_PWSALT FS_IOC_GET_ENCRYPTION_PWSALT
|
#define F2FS_IOC_GET_ENCRYPTION_PWSALT FS_IOC_GET_ENCRYPTION_PWSALT
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <linux/uio.h>
|
#include <linux/uio.h>
|
||||||
#include <linux/uuid.h>
|
#include <linux/uuid.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
|
#include <linux/nls.h>
|
||||||
|
|
||||||
#include "f2fs.h"
|
#include "f2fs.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
@ -3081,6 +3082,68 @@ static int f2fs_ioc_resize_fs(struct file *filp, unsigned long arg)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int f2fs_get_volume_name(struct file *filp, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct inode *inode = file_inode(filp);
|
||||||
|
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||||
|
char *vbuf;
|
||||||
|
int count;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
vbuf = f2fs_kzalloc(sbi, MAX_VOLUME_NAME, GFP_KERNEL);
|
||||||
|
if (!vbuf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
down_read(&sbi->sb_lock);
|
||||||
|
count = utf16s_to_utf8s(sbi->raw_super->volume_name,
|
||||||
|
ARRAY_SIZE(sbi->raw_super->volume_name),
|
||||||
|
UTF16_LITTLE_ENDIAN, vbuf, MAX_VOLUME_NAME);
|
||||||
|
up_read(&sbi->sb_lock);
|
||||||
|
|
||||||
|
if (copy_to_user((char __user *)arg, vbuf,
|
||||||
|
min(FSLABEL_MAX, count)))
|
||||||
|
err = -EFAULT;
|
||||||
|
|
||||||
|
kvfree(vbuf);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f2fs_set_volume_name(struct file *filp, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct inode *inode = file_inode(filp);
|
||||||
|
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||||
|
char *vbuf;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
vbuf = strndup_user((const char __user *)arg, FSLABEL_MAX);
|
||||||
|
if (IS_ERR(vbuf))
|
||||||
|
return PTR_ERR(vbuf);
|
||||||
|
|
||||||
|
err = mnt_want_write_file(filp);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
down_write(&sbi->sb_lock);
|
||||||
|
|
||||||
|
memset(sbi->raw_super->volume_name, 0,
|
||||||
|
sizeof(sbi->raw_super->volume_name));
|
||||||
|
utf8s_to_utf16s(vbuf, strlen(vbuf), UTF16_LITTLE_ENDIAN,
|
||||||
|
sbi->raw_super->volume_name,
|
||||||
|
ARRAY_SIZE(sbi->raw_super->volume_name));
|
||||||
|
|
||||||
|
err = f2fs_commit_super(sbi, false);
|
||||||
|
|
||||||
|
up_write(&sbi->sb_lock);
|
||||||
|
|
||||||
|
mnt_drop_write_file(filp);
|
||||||
|
out:
|
||||||
|
kfree(vbuf);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -3144,6 +3207,10 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
return f2fs_ioc_precache_extents(filp, arg);
|
return f2fs_ioc_precache_extents(filp, arg);
|
||||||
case F2FS_IOC_RESIZE_FS:
|
case F2FS_IOC_RESIZE_FS:
|
||||||
return f2fs_ioc_resize_fs(filp, arg);
|
return f2fs_ioc_resize_fs(filp, arg);
|
||||||
|
case F2FS_IOC_GET_VOLUME_NAME:
|
||||||
|
return f2fs_get_volume_name(filp, arg);
|
||||||
|
case F2FS_IOC_SET_VOLUME_NAME:
|
||||||
|
return f2fs_set_volume_name(filp, arg);
|
||||||
default:
|
default:
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
}
|
}
|
||||||
|
@ -3253,6 +3320,8 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
case F2FS_IOC_SET_PIN_FILE:
|
case F2FS_IOC_SET_PIN_FILE:
|
||||||
case F2FS_IOC_PRECACHE_EXTENTS:
|
case F2FS_IOC_PRECACHE_EXTENTS:
|
||||||
case F2FS_IOC_RESIZE_FS:
|
case F2FS_IOC_RESIZE_FS:
|
||||||
|
case F2FS_IOC_GET_VOLUME_NAME:
|
||||||
|
case F2FS_IOC_SET_VOLUME_NAME:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
|
Loading…
Reference in New Issue