Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * This file is part of UBIFS.
0004  *
0005  * Copyright (C) 2006-2008 Nokia Corporation.
0006  * Copyright (C) 2006, 2007 University of Szeged, Hungary
0007  *
0008  * Authors: Zoltan Sogor
0009  *          Artem Bityutskiy (Битюцкий Артём)
0010  *          Adrian Hunter
0011  */
0012 
0013 /* This file implements EXT2-compatible extended attribute ioctl() calls */
0014 
0015 #include <linux/compat.h>
0016 #include <linux/mount.h>
0017 #include <linux/fileattr.h>
0018 #include "ubifs.h"
0019 
0020 /* Need to be kept consistent with checked flags in ioctl2ubifs() */
0021 #define UBIFS_SETTABLE_IOCTL_FLAGS \
0022     (FS_COMPR_FL | FS_SYNC_FL | FS_APPEND_FL | \
0023      FS_IMMUTABLE_FL | FS_DIRSYNC_FL)
0024 
0025 /* Need to be kept consistent with checked flags in ubifs2ioctl() */
0026 #define UBIFS_GETTABLE_IOCTL_FLAGS \
0027     (UBIFS_SETTABLE_IOCTL_FLAGS | FS_ENCRYPT_FL)
0028 
0029 /**
0030  * ubifs_set_inode_flags - set VFS inode flags.
0031  * @inode: VFS inode to set flags for
0032  *
0033  * This function propagates flags from UBIFS inode object to VFS inode object.
0034  */
0035 void ubifs_set_inode_flags(struct inode *inode)
0036 {
0037     unsigned int flags = ubifs_inode(inode)->flags;
0038 
0039     inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_DIRSYNC |
0040                 S_ENCRYPTED);
0041     if (flags & UBIFS_SYNC_FL)
0042         inode->i_flags |= S_SYNC;
0043     if (flags & UBIFS_APPEND_FL)
0044         inode->i_flags |= S_APPEND;
0045     if (flags & UBIFS_IMMUTABLE_FL)
0046         inode->i_flags |= S_IMMUTABLE;
0047     if (flags & UBIFS_DIRSYNC_FL)
0048         inode->i_flags |= S_DIRSYNC;
0049     if (flags & UBIFS_CRYPT_FL)
0050         inode->i_flags |= S_ENCRYPTED;
0051 }
0052 
0053 /*
0054  * ioctl2ubifs - convert ioctl inode flags to UBIFS inode flags.
0055  * @ioctl_flags: flags to convert
0056  *
0057  * This function converts ioctl flags (@FS_COMPR_FL, etc) to UBIFS inode flags
0058  * (@UBIFS_COMPR_FL, etc).
0059  */
0060 static int ioctl2ubifs(int ioctl_flags)
0061 {
0062     int ubifs_flags = 0;
0063 
0064     if (ioctl_flags & FS_COMPR_FL)
0065         ubifs_flags |= UBIFS_COMPR_FL;
0066     if (ioctl_flags & FS_SYNC_FL)
0067         ubifs_flags |= UBIFS_SYNC_FL;
0068     if (ioctl_flags & FS_APPEND_FL)
0069         ubifs_flags |= UBIFS_APPEND_FL;
0070     if (ioctl_flags & FS_IMMUTABLE_FL)
0071         ubifs_flags |= UBIFS_IMMUTABLE_FL;
0072     if (ioctl_flags & FS_DIRSYNC_FL)
0073         ubifs_flags |= UBIFS_DIRSYNC_FL;
0074 
0075     return ubifs_flags;
0076 }
0077 
0078 /*
0079  * ubifs2ioctl - convert UBIFS inode flags to ioctl inode flags.
0080  * @ubifs_flags: flags to convert
0081  *
0082  * This function converts UBIFS inode flags (@UBIFS_COMPR_FL, etc) to ioctl
0083  * flags (@FS_COMPR_FL, etc).
0084  */
0085 static int ubifs2ioctl(int ubifs_flags)
0086 {
0087     int ioctl_flags = 0;
0088 
0089     if (ubifs_flags & UBIFS_COMPR_FL)
0090         ioctl_flags |= FS_COMPR_FL;
0091     if (ubifs_flags & UBIFS_SYNC_FL)
0092         ioctl_flags |= FS_SYNC_FL;
0093     if (ubifs_flags & UBIFS_APPEND_FL)
0094         ioctl_flags |= FS_APPEND_FL;
0095     if (ubifs_flags & UBIFS_IMMUTABLE_FL)
0096         ioctl_flags |= FS_IMMUTABLE_FL;
0097     if (ubifs_flags & UBIFS_DIRSYNC_FL)
0098         ioctl_flags |= FS_DIRSYNC_FL;
0099     if (ubifs_flags & UBIFS_CRYPT_FL)
0100         ioctl_flags |= FS_ENCRYPT_FL;
0101 
0102     return ioctl_flags;
0103 }
0104 
0105 static int setflags(struct inode *inode, int flags)
0106 {
0107     int err, release;
0108     struct ubifs_inode *ui = ubifs_inode(inode);
0109     struct ubifs_info *c = inode->i_sb->s_fs_info;
0110     struct ubifs_budget_req req = { .dirtied_ino = 1,
0111             .dirtied_ino_d = ALIGN(ui->data_len, 8) };
0112 
0113     err = ubifs_budget_space(c, &req);
0114     if (err)
0115         return err;
0116 
0117     mutex_lock(&ui->ui_mutex);
0118     ui->flags &= ~ioctl2ubifs(UBIFS_SETTABLE_IOCTL_FLAGS);
0119     ui->flags |= ioctl2ubifs(flags);
0120     ubifs_set_inode_flags(inode);
0121     inode->i_ctime = current_time(inode);
0122     release = ui->dirty;
0123     mark_inode_dirty_sync(inode);
0124     mutex_unlock(&ui->ui_mutex);
0125 
0126     if (release)
0127         ubifs_release_budget(c, &req);
0128     if (IS_SYNC(inode))
0129         err = write_inode_now(inode, 1);
0130     return err;
0131 }
0132 
0133 int ubifs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
0134 {
0135     struct inode *inode = d_inode(dentry);
0136     int flags = ubifs2ioctl(ubifs_inode(inode)->flags);
0137 
0138     if (d_is_special(dentry))
0139         return -ENOTTY;
0140 
0141     dbg_gen("get flags: %#x, i_flags %#x", flags, inode->i_flags);
0142     fileattr_fill_flags(fa, flags);
0143 
0144     return 0;
0145 }
0146 
0147 int ubifs_fileattr_set(struct user_namespace *mnt_userns,
0148                struct dentry *dentry, struct fileattr *fa)
0149 {
0150     struct inode *inode = d_inode(dentry);
0151     int flags = fa->flags;
0152 
0153     if (d_is_special(dentry))
0154         return -ENOTTY;
0155 
0156     if (fileattr_has_fsx(fa))
0157         return -EOPNOTSUPP;
0158 
0159     if (flags & ~UBIFS_GETTABLE_IOCTL_FLAGS)
0160         return -EOPNOTSUPP;
0161 
0162     flags &= UBIFS_SETTABLE_IOCTL_FLAGS;
0163 
0164     if (!S_ISDIR(inode->i_mode))
0165         flags &= ~FS_DIRSYNC_FL;
0166 
0167     dbg_gen("set flags: %#x, i_flags %#x", flags, inode->i_flags);
0168     return setflags(inode, flags);
0169 }
0170 
0171 long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0172 {
0173     int err;
0174     struct inode *inode = file_inode(file);
0175 
0176     switch (cmd) {
0177     case FS_IOC_SET_ENCRYPTION_POLICY: {
0178         struct ubifs_info *c = inode->i_sb->s_fs_info;
0179 
0180         err = ubifs_enable_encryption(c);
0181         if (err)
0182             return err;
0183 
0184         return fscrypt_ioctl_set_policy(file, (const void __user *)arg);
0185     }
0186     case FS_IOC_GET_ENCRYPTION_POLICY:
0187         return fscrypt_ioctl_get_policy(file, (void __user *)arg);
0188 
0189     case FS_IOC_GET_ENCRYPTION_POLICY_EX:
0190         return fscrypt_ioctl_get_policy_ex(file, (void __user *)arg);
0191 
0192     case FS_IOC_ADD_ENCRYPTION_KEY:
0193         return fscrypt_ioctl_add_key(file, (void __user *)arg);
0194 
0195     case FS_IOC_REMOVE_ENCRYPTION_KEY:
0196         return fscrypt_ioctl_remove_key(file, (void __user *)arg);
0197 
0198     case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
0199         return fscrypt_ioctl_remove_key_all_users(file,
0200                               (void __user *)arg);
0201     case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
0202         return fscrypt_ioctl_get_key_status(file, (void __user *)arg);
0203 
0204     case FS_IOC_GET_ENCRYPTION_NONCE:
0205         return fscrypt_ioctl_get_nonce(file, (void __user *)arg);
0206 
0207     default:
0208         return -ENOTTY;
0209     }
0210 }
0211 
0212 #ifdef CONFIG_COMPAT
0213 long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0214 {
0215     switch (cmd) {
0216     case FS_IOC32_GETFLAGS:
0217         cmd = FS_IOC_GETFLAGS;
0218         break;
0219     case FS_IOC32_SETFLAGS:
0220         cmd = FS_IOC_SETFLAGS;
0221         break;
0222     case FS_IOC_SET_ENCRYPTION_POLICY:
0223     case FS_IOC_GET_ENCRYPTION_POLICY:
0224     case FS_IOC_GET_ENCRYPTION_POLICY_EX:
0225     case FS_IOC_ADD_ENCRYPTION_KEY:
0226     case FS_IOC_REMOVE_ENCRYPTION_KEY:
0227     case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
0228     case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
0229     case FS_IOC_GET_ENCRYPTION_NONCE:
0230         break;
0231     default:
0232         return -ENOIOCTLCMD;
0233     }
0234     return ubifs_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
0235 }
0236 #endif