1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * linux/fs/ext2/ioctl.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 1993, 1994, 1995 61da177e4SLinus Torvalds * Remy Card (card@masi.ibp.fr) 71da177e4SLinus Torvalds * Laboratoire MASI - Institut Blaise Pascal 81da177e4SLinus Torvalds * Universite Pierre et Marie Curie (Paris VI) 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds #include "ext2.h" 1216f7e0feSRandy Dunlap #include <linux/capability.h> 131da177e4SLinus Torvalds #include <linux/time.h> 141da177e4SLinus Torvalds #include <linux/sched.h> 15e322ff07SDavid Howells #include <linux/compat.h> 1642a74f20SDave Hansen #include <linux/mount.h> 171da177e4SLinus Torvalds #include <asm/current.h> 187c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 19aba405e3SMiklos Szeredi #include <linux/fileattr.h> 20aba405e3SMiklos Szeredi 21aba405e3SMiklos Szeredi int ext2_fileattr_get(struct dentry *dentry, struct fileattr *fa) 22aba405e3SMiklos Szeredi { 23aba405e3SMiklos Szeredi struct ext2_inode_info *ei = EXT2_I(d_inode(dentry)); 24aba405e3SMiklos Szeredi 25aba405e3SMiklos Szeredi fileattr_fill_flags(fa, ei->i_flags & EXT2_FL_USER_VISIBLE); 26aba405e3SMiklos Szeredi 27aba405e3SMiklos Szeredi return 0; 28aba405e3SMiklos Szeredi } 29aba405e3SMiklos Szeredi 30*8782a9aeSChristian Brauner int ext2_fileattr_set(struct mnt_idmap *idmap, 31aba405e3SMiklos Szeredi struct dentry *dentry, struct fileattr *fa) 32aba405e3SMiklos Szeredi { 33aba405e3SMiklos Szeredi struct inode *inode = d_inode(dentry); 34aba405e3SMiklos Szeredi struct ext2_inode_info *ei = EXT2_I(inode); 35aba405e3SMiklos Szeredi 36aba405e3SMiklos Szeredi if (fileattr_has_fsx(fa)) 37aba405e3SMiklos Szeredi return -EOPNOTSUPP; 38aba405e3SMiklos Szeredi 39aba405e3SMiklos Szeredi /* Is it quota file? Do not allow user to mess with it */ 40aba405e3SMiklos Szeredi if (IS_NOQUOTA(inode)) 41aba405e3SMiklos Szeredi return -EPERM; 42aba405e3SMiklos Szeredi 43aba405e3SMiklos Szeredi ei->i_flags = (ei->i_flags & ~EXT2_FL_USER_MODIFIABLE) | 44aba405e3SMiklos Szeredi (fa->flags & EXT2_FL_USER_MODIFIABLE); 45aba405e3SMiklos Szeredi 46aba405e3SMiklos Szeredi ext2_set_inode_flags(inode); 47aba405e3SMiklos Szeredi inode->i_ctime = current_time(inode); 48aba405e3SMiklos Szeredi mark_inode_dirty(inode); 49aba405e3SMiklos Szeredi 50aba405e3SMiklos Szeredi return 0; 51aba405e3SMiklos Szeredi } 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds 5414f9f7b2SAndi Kleen long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 551da177e4SLinus Torvalds { 56496ad9aaSAl Viro struct inode *inode = file_inode(filp); 571da177e4SLinus Torvalds struct ext2_inode_info *ei = EXT2_I(inode); 58a686cd89SMartin J. Bligh unsigned short rsv_window_size; 5942a74f20SDave Hansen int ret; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg); 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds switch (cmd) { 641da177e4SLinus Torvalds case EXT2_IOC_GETVERSION: 651da177e4SLinus Torvalds return put_user(inode->i_generation, (int __user *) arg); 6634b07840SDjalal Harouni case EXT2_IOC_SETVERSION: { 6734b07840SDjalal Harouni __u32 generation; 6834b07840SDjalal Harouni 6921cb47beSChristian Brauner if (!inode_owner_or_capable(&init_user_ns, inode)) 701da177e4SLinus Torvalds return -EPERM; 71a561be71SAl Viro ret = mnt_want_write_file(filp); 7242a74f20SDave Hansen if (ret) 7342a74f20SDave Hansen return ret; 7434b07840SDjalal Harouni if (get_user(generation, (int __user *) arg)) { 7542a74f20SDave Hansen ret = -EFAULT; 7634b07840SDjalal Harouni goto setversion_out; 7742a74f20SDave Hansen } 7834b07840SDjalal Harouni 795955102cSAl Viro inode_lock(inode); 8002027d42SDeepa Dinamani inode->i_ctime = current_time(inode); 8134b07840SDjalal Harouni inode->i_generation = generation; 825955102cSAl Viro inode_unlock(inode); 8334b07840SDjalal Harouni 8434b07840SDjalal Harouni mark_inode_dirty(inode); 8534b07840SDjalal Harouni setversion_out: 862a79f17eSAl Viro mnt_drop_write_file(filp); 8742a74f20SDave Hansen return ret; 8834b07840SDjalal Harouni } 89a686cd89SMartin J. Bligh case EXT2_IOC_GETRSVSZ: 90a686cd89SMartin J. Bligh if (test_opt(inode->i_sb, RESERVATION) 91a686cd89SMartin J. Bligh && S_ISREG(inode->i_mode) 92a686cd89SMartin J. Bligh && ei->i_block_alloc_info) { 93a686cd89SMartin J. Bligh rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size; 94a686cd89SMartin J. Bligh return put_user(rsv_window_size, (int __user *)arg); 95a686cd89SMartin J. Bligh } 96a686cd89SMartin J. Bligh return -ENOTTY; 97a686cd89SMartin J. Bligh case EXT2_IOC_SETRSVSZ: { 98a686cd89SMartin J. Bligh 99a686cd89SMartin J. Bligh if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) 100a686cd89SMartin J. Bligh return -ENOTTY; 101a686cd89SMartin J. Bligh 10221cb47beSChristian Brauner if (!inode_owner_or_capable(&init_user_ns, inode)) 103a686cd89SMartin J. Bligh return -EACCES; 104a686cd89SMartin J. Bligh 105a686cd89SMartin J. Bligh if (get_user(rsv_window_size, (int __user *)arg)) 106a686cd89SMartin J. Bligh return -EFAULT; 107a686cd89SMartin J. Bligh 108a561be71SAl Viro ret = mnt_want_write_file(filp); 10942a74f20SDave Hansen if (ret) 11042a74f20SDave Hansen return ret; 11142a74f20SDave Hansen 112a686cd89SMartin J. Bligh if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS) 113a686cd89SMartin J. Bligh rsv_window_size = EXT2_MAX_RESERVE_BLOCKS; 114a686cd89SMartin J. Bligh 115a686cd89SMartin J. Bligh /* 116a686cd89SMartin J. Bligh * need to allocate reservation structure for this inode 117a686cd89SMartin J. Bligh * before set the window size 118a686cd89SMartin J. Bligh */ 119a686cd89SMartin J. Bligh /* 120a686cd89SMartin J. Bligh * XXX What lock should protect the rsv_goal_size? 121a686cd89SMartin J. Bligh * Accessed in ext2_get_block only. ext3 uses i_truncate. 122a686cd89SMartin J. Bligh */ 123a686cd89SMartin J. Bligh mutex_lock(&ei->truncate_mutex); 124a686cd89SMartin J. Bligh if (!ei->i_block_alloc_info) 125a686cd89SMartin J. Bligh ext2_init_block_alloc_info(inode); 126a686cd89SMartin J. Bligh 127a686cd89SMartin J. Bligh if (ei->i_block_alloc_info){ 128a686cd89SMartin J. Bligh struct ext2_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node; 129a686cd89SMartin J. Bligh rsv->rsv_goal_size = rsv_window_size; 130acd1f046SChengguang Xu } else { 131acd1f046SChengguang Xu ret = -ENOMEM; 132a686cd89SMartin J. Bligh } 133acd1f046SChengguang Xu 134a686cd89SMartin J. Bligh mutex_unlock(&ei->truncate_mutex); 1352a79f17eSAl Viro mnt_drop_write_file(filp); 136acd1f046SChengguang Xu return ret; 137a686cd89SMartin J. Bligh } 1381da177e4SLinus Torvalds default: 1391da177e4SLinus Torvalds return -ENOTTY; 1401da177e4SLinus Torvalds } 1411da177e4SLinus Torvalds } 142e322ff07SDavid Howells 143e322ff07SDavid Howells #ifdef CONFIG_COMPAT 144e322ff07SDavid Howells long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 145e322ff07SDavid Howells { 146e322ff07SDavid Howells /* These are just misnamed, they actually get/put from/to user an int */ 147e322ff07SDavid Howells switch (cmd) { 148e322ff07SDavid Howells case EXT2_IOC32_GETVERSION: 149e322ff07SDavid Howells cmd = EXT2_IOC_GETVERSION; 150e322ff07SDavid Howells break; 151e322ff07SDavid Howells case EXT2_IOC32_SETVERSION: 152e322ff07SDavid Howells cmd = EXT2_IOC_SETVERSION; 153e322ff07SDavid Howells break; 154e322ff07SDavid Howells default: 155e322ff07SDavid Howells return -ENOIOCTLCMD; 156e322ff07SDavid Howells } 15714f9f7b2SAndi Kleen return ext2_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); 158e322ff07SDavid Howells } 159e322ff07SDavid Howells #endif 160