cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ioctl.c (6188B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * This file is part of UBIFS.
      4 *
      5 * Copyright (C) 2006-2008 Nokia Corporation.
      6 * Copyright (C) 2006, 2007 University of Szeged, Hungary
      7 *
      8 * Authors: Zoltan Sogor
      9 *          Artem Bityutskiy (Битюцкий Артём)
     10 *          Adrian Hunter
     11 */
     12
     13/* This file implements EXT2-compatible extended attribute ioctl() calls */
     14
     15#include <linux/compat.h>
     16#include <linux/mount.h>
     17#include <linux/fileattr.h>
     18#include "ubifs.h"
     19
     20/* Need to be kept consistent with checked flags in ioctl2ubifs() */
     21#define UBIFS_SETTABLE_IOCTL_FLAGS \
     22	(FS_COMPR_FL | FS_SYNC_FL | FS_APPEND_FL | \
     23	 FS_IMMUTABLE_FL | FS_DIRSYNC_FL)
     24
     25/* Need to be kept consistent with checked flags in ubifs2ioctl() */
     26#define UBIFS_GETTABLE_IOCTL_FLAGS \
     27	(UBIFS_SETTABLE_IOCTL_FLAGS | FS_ENCRYPT_FL)
     28
     29/**
     30 * ubifs_set_inode_flags - set VFS inode flags.
     31 * @inode: VFS inode to set flags for
     32 *
     33 * This function propagates flags from UBIFS inode object to VFS inode object.
     34 */
     35void ubifs_set_inode_flags(struct inode *inode)
     36{
     37	unsigned int flags = ubifs_inode(inode)->flags;
     38
     39	inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_DIRSYNC |
     40			    S_ENCRYPTED);
     41	if (flags & UBIFS_SYNC_FL)
     42		inode->i_flags |= S_SYNC;
     43	if (flags & UBIFS_APPEND_FL)
     44		inode->i_flags |= S_APPEND;
     45	if (flags & UBIFS_IMMUTABLE_FL)
     46		inode->i_flags |= S_IMMUTABLE;
     47	if (flags & UBIFS_DIRSYNC_FL)
     48		inode->i_flags |= S_DIRSYNC;
     49	if (flags & UBIFS_CRYPT_FL)
     50		inode->i_flags |= S_ENCRYPTED;
     51}
     52
     53/*
     54 * ioctl2ubifs - convert ioctl inode flags to UBIFS inode flags.
     55 * @ioctl_flags: flags to convert
     56 *
     57 * This function converts ioctl flags (@FS_COMPR_FL, etc) to UBIFS inode flags
     58 * (@UBIFS_COMPR_FL, etc).
     59 */
     60static int ioctl2ubifs(int ioctl_flags)
     61{
     62	int ubifs_flags = 0;
     63
     64	if (ioctl_flags & FS_COMPR_FL)
     65		ubifs_flags |= UBIFS_COMPR_FL;
     66	if (ioctl_flags & FS_SYNC_FL)
     67		ubifs_flags |= UBIFS_SYNC_FL;
     68	if (ioctl_flags & FS_APPEND_FL)
     69		ubifs_flags |= UBIFS_APPEND_FL;
     70	if (ioctl_flags & FS_IMMUTABLE_FL)
     71		ubifs_flags |= UBIFS_IMMUTABLE_FL;
     72	if (ioctl_flags & FS_DIRSYNC_FL)
     73		ubifs_flags |= UBIFS_DIRSYNC_FL;
     74
     75	return ubifs_flags;
     76}
     77
     78/*
     79 * ubifs2ioctl - convert UBIFS inode flags to ioctl inode flags.
     80 * @ubifs_flags: flags to convert
     81 *
     82 * This function converts UBIFS inode flags (@UBIFS_COMPR_FL, etc) to ioctl
     83 * flags (@FS_COMPR_FL, etc).
     84 */
     85static int ubifs2ioctl(int ubifs_flags)
     86{
     87	int ioctl_flags = 0;
     88
     89	if (ubifs_flags & UBIFS_COMPR_FL)
     90		ioctl_flags |= FS_COMPR_FL;
     91	if (ubifs_flags & UBIFS_SYNC_FL)
     92		ioctl_flags |= FS_SYNC_FL;
     93	if (ubifs_flags & UBIFS_APPEND_FL)
     94		ioctl_flags |= FS_APPEND_FL;
     95	if (ubifs_flags & UBIFS_IMMUTABLE_FL)
     96		ioctl_flags |= FS_IMMUTABLE_FL;
     97	if (ubifs_flags & UBIFS_DIRSYNC_FL)
     98		ioctl_flags |= FS_DIRSYNC_FL;
     99	if (ubifs_flags & UBIFS_CRYPT_FL)
    100		ioctl_flags |= FS_ENCRYPT_FL;
    101
    102	return ioctl_flags;
    103}
    104
    105static int setflags(struct inode *inode, int flags)
    106{
    107	int err, release;
    108	struct ubifs_inode *ui = ubifs_inode(inode);
    109	struct ubifs_info *c = inode->i_sb->s_fs_info;
    110	struct ubifs_budget_req req = { .dirtied_ino = 1,
    111			.dirtied_ino_d = ALIGN(ui->data_len, 8) };
    112
    113	err = ubifs_budget_space(c, &req);
    114	if (err)
    115		return err;
    116
    117	mutex_lock(&ui->ui_mutex);
    118	ui->flags &= ~ioctl2ubifs(UBIFS_SETTABLE_IOCTL_FLAGS);
    119	ui->flags |= ioctl2ubifs(flags);
    120	ubifs_set_inode_flags(inode);
    121	inode->i_ctime = current_time(inode);
    122	release = ui->dirty;
    123	mark_inode_dirty_sync(inode);
    124	mutex_unlock(&ui->ui_mutex);
    125
    126	if (release)
    127		ubifs_release_budget(c, &req);
    128	if (IS_SYNC(inode))
    129		err = write_inode_now(inode, 1);
    130	return err;
    131}
    132
    133int ubifs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
    134{
    135	struct inode *inode = d_inode(dentry);
    136	int flags = ubifs2ioctl(ubifs_inode(inode)->flags);
    137
    138	if (d_is_special(dentry))
    139		return -ENOTTY;
    140
    141	dbg_gen("get flags: %#x, i_flags %#x", flags, inode->i_flags);
    142	fileattr_fill_flags(fa, flags);
    143
    144	return 0;
    145}
    146
    147int ubifs_fileattr_set(struct user_namespace *mnt_userns,
    148		       struct dentry *dentry, struct fileattr *fa)
    149{
    150	struct inode *inode = d_inode(dentry);
    151	int flags = fa->flags;
    152
    153	if (d_is_special(dentry))
    154		return -ENOTTY;
    155
    156	if (fileattr_has_fsx(fa))
    157		return -EOPNOTSUPP;
    158
    159	if (flags & ~UBIFS_GETTABLE_IOCTL_FLAGS)
    160		return -EOPNOTSUPP;
    161
    162	flags &= UBIFS_SETTABLE_IOCTL_FLAGS;
    163
    164	if (!S_ISDIR(inode->i_mode))
    165		flags &= ~FS_DIRSYNC_FL;
    166
    167	dbg_gen("set flags: %#x, i_flags %#x", flags, inode->i_flags);
    168	return setflags(inode, flags);
    169}
    170
    171long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    172{
    173	int err;
    174	struct inode *inode = file_inode(file);
    175
    176	switch (cmd) {
    177	case FS_IOC_SET_ENCRYPTION_POLICY: {
    178		struct ubifs_info *c = inode->i_sb->s_fs_info;
    179
    180		err = ubifs_enable_encryption(c);
    181		if (err)
    182			return err;
    183
    184		return fscrypt_ioctl_set_policy(file, (const void __user *)arg);
    185	}
    186	case FS_IOC_GET_ENCRYPTION_POLICY:
    187		return fscrypt_ioctl_get_policy(file, (void __user *)arg);
    188
    189	case FS_IOC_GET_ENCRYPTION_POLICY_EX:
    190		return fscrypt_ioctl_get_policy_ex(file, (void __user *)arg);
    191
    192	case FS_IOC_ADD_ENCRYPTION_KEY:
    193		return fscrypt_ioctl_add_key(file, (void __user *)arg);
    194
    195	case FS_IOC_REMOVE_ENCRYPTION_KEY:
    196		return fscrypt_ioctl_remove_key(file, (void __user *)arg);
    197
    198	case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
    199		return fscrypt_ioctl_remove_key_all_users(file,
    200							  (void __user *)arg);
    201	case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
    202		return fscrypt_ioctl_get_key_status(file, (void __user *)arg);
    203
    204	case FS_IOC_GET_ENCRYPTION_NONCE:
    205		return fscrypt_ioctl_get_nonce(file, (void __user *)arg);
    206
    207	default:
    208		return -ENOTTY;
    209	}
    210}
    211
    212#ifdef CONFIG_COMPAT
    213long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    214{
    215	switch (cmd) {
    216	case FS_IOC32_GETFLAGS:
    217		cmd = FS_IOC_GETFLAGS;
    218		break;
    219	case FS_IOC32_SETFLAGS:
    220		cmd = FS_IOC_SETFLAGS;
    221		break;
    222	case FS_IOC_SET_ENCRYPTION_POLICY:
    223	case FS_IOC_GET_ENCRYPTION_POLICY:
    224	case FS_IOC_GET_ENCRYPTION_POLICY_EX:
    225	case FS_IOC_ADD_ENCRYPTION_KEY:
    226	case FS_IOC_REMOVE_ENCRYPTION_KEY:
    227	case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
    228	case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
    229	case FS_IOC_GET_ENCRYPTION_NONCE:
    230		break;
    231	default:
    232		return -ENOIOCTLCMD;
    233	}
    234	return ubifs_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
    235}
    236#endif