You've already forked linux-apfs-rw
mirror of
https://github.com/linux-apfs/linux-apfs-rw.git
synced 2026-05-01 15:01:34 -07:00
Fix SETFLAGS/GETFLAGS ioctls for newer kernels
Luflosi is reporting new build issues: https://github.com/linux-apfs/linux-apfs-rw/issues/19 These problems started when I implemented the FS_IOC_SETFLAGS and FS_IOC_GETFLAGS ioctls. These ioctls have become officially supported by the vfs recently, and then some of the helpers I was using got removed. The proper way to implement this in newer kernels is through inode methods ->apfs_fileattr_get() and ->apfs_fileattr_set(). So do that, and also fix a new instance of the typical build issue with new namespace parameters. This time I've taken the trouble to build-test this with a 5.13 kernel, and I even ran xfstests, so there shouldn't be any more problems, at least not with that version. Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
This commit is contained in:
@@ -788,6 +788,11 @@ extern int apfs_getattr(struct user_namespace *mnt_userns,
|
||||
extern int apfs_crypto_adj_refcnt(struct super_block *sb, u64 crypto_id, int delta);
|
||||
extern int APFS_CRYPTO_ADJ_REFCNT_MAXOPS(void);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
|
||||
extern int apfs_fileattr_get(struct dentry *dentry, struct fileattr *fa);
|
||||
extern int apfs_fileattr_set(struct user_namespace *mnt_userns, struct dentry *dentry, struct fileattr *fa);
|
||||
#endif
|
||||
|
||||
/* key.c */
|
||||
extern int apfs_filename_cmp(struct super_block *sb,
|
||||
const char *name1, const char *name2);
|
||||
|
||||
@@ -131,4 +131,8 @@ const struct inode_operations apfs_file_inode_operations = {
|
||||
.listxattr = apfs_listxattr,
|
||||
.setattr = apfs_setattr,
|
||||
.update_time = apfs_update_time,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
|
||||
.fileattr_get = apfs_fileattr_get,
|
||||
.fileattr_set = apfs_fileattr_set,
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include <linux/blk_types.h>
|
||||
#include "apfs.h"
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
|
||||
#include <linux/fileattr.h>
|
||||
#endif
|
||||
|
||||
#define MAX_PFK_LEN 512
|
||||
|
||||
static int apfs_readpage(struct file *file, struct page *page)
|
||||
@@ -1756,20 +1760,6 @@ static unsigned int apfs_getflags(struct inode *inode)
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* apfs_ioc_getflags - Ioctl handler for FS_IOC_GETFLAGS
|
||||
* @file: affected file
|
||||
* @arg: ioctl argument
|
||||
*
|
||||
* Returns 0 on success, or a negative error code in case of failure.
|
||||
*/
|
||||
static int apfs_ioc_getflags(struct file *file, int __user *arg)
|
||||
{
|
||||
unsigned int flags = apfs_getflags(file_inode(file));
|
||||
|
||||
return put_user(flags, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* apfs_setflags - Set an inode's bsd flags
|
||||
* @inode: the vfs inode
|
||||
@@ -1802,6 +1792,22 @@ static void apfs_setflags(struct inode *inode, unsigned int flags)
|
||||
inode_set_flags(inode, i_flags, S_IMMUTABLE | S_APPEND);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0)
|
||||
|
||||
/**
|
||||
* apfs_ioc_getflags - Ioctl handler for FS_IOC_GETFLAGS
|
||||
* @file: affected file
|
||||
* @arg: ioctl argument
|
||||
*
|
||||
* Returns 0 on success, or a negative error code in case of failure.
|
||||
*/
|
||||
static int apfs_ioc_getflags(struct file *file, int __user *arg)
|
||||
{
|
||||
unsigned int flags = apfs_getflags(file_inode(file));
|
||||
|
||||
return put_user(flags, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* apfs_do_ioc_setflags - Actual work for apfs_ioc_setflags(), after preparation
|
||||
* @inode: affected vfs inode
|
||||
@@ -1856,7 +1862,11 @@ static int apfs_ioc_setflags(struct file *file, int __user *arg)
|
||||
if (sb->s_flags & SB_RDONLY)
|
||||
return -EROFS;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
|
||||
if (!inode_owner_or_capable(inode))
|
||||
#else
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
#endif
|
||||
return -EPERM;
|
||||
|
||||
if (get_user(newflags, arg))
|
||||
@@ -1877,15 +1887,62 @@ static int apfs_ioc_setflags(struct file *file, int __user *arg)
|
||||
return err;
|
||||
}
|
||||
|
||||
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0) */
|
||||
|
||||
int apfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
|
||||
{
|
||||
unsigned int flags = apfs_getflags(d_inode(dentry));
|
||||
|
||||
fileattr_fill_flags(fa, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apfs_fileattr_set(struct user_namespace *mnt_userns, struct dentry *dentry, struct fileattr *fa)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct apfs_max_ops maxops;
|
||||
int err;
|
||||
|
||||
if (sb->s_flags & SB_RDONLY)
|
||||
return -EROFS;
|
||||
|
||||
if (fa->flags & ~(FS_APPEND_FL | FS_IMMUTABLE_FL | FS_NODUMP_FL))
|
||||
return -EOPNOTSUPP;
|
||||
if (fileattr_has_fsx(fa))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
lockdep_assert_held_write(&inode->i_rwsem);
|
||||
|
||||
maxops.cat = APFS_UPDATE_INODE_MAXOPS();
|
||||
maxops.blks = 0;
|
||||
err = apfs_transaction_start(sb, maxops);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
apfs_inode_join_transaction(sb, inode);
|
||||
apfs_setflags(inode, fa->flags);
|
||||
inode->i_ctime = current_time(inode);
|
||||
|
||||
err = apfs_transaction_commit(sb);
|
||||
if (err)
|
||||
apfs_transaction_abort(sb);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0) */
|
||||
|
||||
long apfs_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
|
||||
switch (cmd) {
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0)
|
||||
case FS_IOC_GETFLAGS:
|
||||
return apfs_ioc_getflags(file, argp);
|
||||
case FS_IOC_SETFLAGS:
|
||||
return apfs_ioc_setflags(file, argp);
|
||||
#endif
|
||||
case APFS_IOC_SET_DFLT_PFK:
|
||||
return apfs_ioc_set_dflt_pfk(file, argp);
|
||||
case APFS_IOC_SET_DIR_CLASS:
|
||||
@@ -1902,10 +1959,12 @@ long apfs_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
void __user *argp = (void __user *)arg;
|
||||
|
||||
switch (cmd) {
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0)
|
||||
case FS_IOC_GETFLAGS:
|
||||
return apfs_ioc_getflags(file, argp);
|
||||
case FS_IOC_SETFLAGS:
|
||||
return apfs_ioc_setflags(file, argp);
|
||||
#endif
|
||||
case APFS_IOC_SET_PFK:
|
||||
return apfs_ioc_set_pfk(file, argp);
|
||||
case APFS_IOC_GET_CLASS:
|
||||
|
||||
@@ -56,6 +56,10 @@ const struct inode_operations apfs_dir_inode_operations = {
|
||||
.listxattr = apfs_listxattr,
|
||||
.setattr = apfs_setattr,
|
||||
.update_time = apfs_update_time,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
|
||||
.fileattr_get = apfs_fileattr_get,
|
||||
.fileattr_set = apfs_fileattr_set,
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct inode_operations apfs_special_inode_operations = {
|
||||
|
||||
Reference in New Issue
Block a user