b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/ext2/ioctl.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Copyright (C) 1993, 1994, 1995
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) * Remy Card (card@masi.ibp.fr)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * Laboratoire MASI - Institut Blaise Pascal
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) * Universite Pierre et Marie Curie (Paris VI)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include "ext2.h"
16f7e0fe2ecc3 (Randy Dunlap 2006-01-11 12:17:46 -0800 12) #include <linux/capability.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) #include <linux/time.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include <linux/sched.h>
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 15) #include <linux/compat.h>
42a74f206b914 (Dave Hansen 2008-02-15 14:37:46 -0800 16) #include <linux/mount.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) #include <asm/current.h>
7c0f6ba682b9c (Linus Torvalds 2016-12-24 11:46:01 -0800 18) #include <linux/uaccess.h>
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 19) #include <linux/fileattr.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 21) int ext2_fileattr_get(struct dentry *dentry, struct fileattr *fa)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) {
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 23) struct ext2_inode_info *ei = EXT2_I(d_inode(dentry));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 25) fileattr_fill_flags(fa, ei->i_flags & EXT2_FL_USER_VISIBLE);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 27) return 0;
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 28) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 30) int ext2_fileattr_set(struct user_namespace *mnt_userns,
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 31) struct dentry *dentry, struct fileattr *fa)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 32) {
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 33) struct inode *inode = d_inode(dentry);
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 34) struct ext2_inode_info *ei = EXT2_I(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 36) if (fileattr_has_fsx(fa))
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 37) return -EOPNOTSUPP;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 38)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 39) /* Is it quota file? Do not allow user to mess with it */
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 40) if (IS_NOQUOTA(inode))
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 41) return -EPERM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 43) ei->i_flags = (ei->i_flags & ~EXT2_FL_USER_MODIFIABLE) |
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 44) (fa->flags & EXT2_FL_USER_MODIFIABLE);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 46) ext2_set_inode_flags(inode);
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 47) inode->i_ctime = current_time(inode);
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 48) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 50) return 0;
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 51) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 53)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 54) long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 55) {
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 56) struct inode *inode = file_inode(filp);
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 57) struct ext2_inode_info *ei = EXT2_I(inode);
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 58) unsigned short rsv_window_size;
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 59) int ret;
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 60)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 61) ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 62)
aba405e33e150 (Miklos Szeredi 2021-04-07 14:36:43 +0200 63) switch (cmd) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 64) case EXT2_IOC_GETVERSION:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 65) return put_user(inode->i_generation, (int __user *) arg);
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 66) case EXT2_IOC_SETVERSION: {
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 67) __u32 generation;
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 68)
21cb47be6fb9e (Christian Brauner 2021-01-21 14:19:25 +0100 69) if (!inode_owner_or_capable(&init_user_ns, inode))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) return -EPERM;
a561be7100cd6 (Al Viro 2011-11-23 11:57:51 -0500 71) ret = mnt_want_write_file(filp);
42a74f206b914 (Dave Hansen 2008-02-15 14:37:46 -0800 72) if (ret)
42a74f206b914 (Dave Hansen 2008-02-15 14:37:46 -0800 73) return ret;
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 74) if (get_user(generation, (int __user *) arg)) {
42a74f206b914 (Dave Hansen 2008-02-15 14:37:46 -0800 75) ret = -EFAULT;
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 76) goto setversion_out;
42a74f206b914 (Dave Hansen 2008-02-15 14:37:46 -0800 77) }
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 78)
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 79) inode_lock(inode);
02027d42c3f74 (Deepa Dinamani 2016-09-14 07:48:05 -0700 80) inode->i_ctime = current_time(inode);
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 81) inode->i_generation = generation;
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 82) inode_unlock(inode);
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 83)
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 84) mark_inode_dirty(inode);
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 85) setversion_out:
2a79f17e4a641 (Al Viro 2011-12-09 08:06:57 -0500 86) mnt_drop_write_file(filp);
42a74f206b914 (Dave Hansen 2008-02-15 14:37:46 -0800 87) return ret;
34b0784056500 (Djalal Harouni 2012-01-09 15:58:37 +0100 88) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 89) case EXT2_IOC_GETRSVSZ:
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 90) if (test_opt(inode->i_sb, RESERVATION)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 91) && S_ISREG(inode->i_mode)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 92) && ei->i_block_alloc_info) {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 93) rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 94) return put_user(rsv_window_size, (int __user *)arg);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 95) }
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 96) return -ENOTTY;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 97) case EXT2_IOC_SETRSVSZ: {
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 98)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 99) if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 100) return -ENOTTY;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 101)
21cb47be6fb9e (Christian Brauner 2021-01-21 14:19:25 +0100 102) if (!inode_owner_or_capable(&init_user_ns, inode))
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 103) return -EACCES;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 104)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 105) if (get_user(rsv_window_size, (int __user *)arg))
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 106) return -EFAULT;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 107)
a561be7100cd6 (Al Viro 2011-11-23 11:57:51 -0500 108) ret = mnt_want_write_file(filp);
42a74f206b914 (Dave Hansen 2008-02-15 14:37:46 -0800 109) if (ret)
42a74f206b914 (Dave Hansen 2008-02-15 14:37:46 -0800 110) return ret;
42a74f206b914 (Dave Hansen 2008-02-15 14:37:46 -0800 111)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 112) if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 113) rsv_window_size = EXT2_MAX_RESERVE_BLOCKS;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 114)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 115) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 116) * need to allocate reservation structure for this inode
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 117) * before set the window size
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 118) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 119) /*
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 120) * XXX What lock should protect the rsv_goal_size?
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 121) * Accessed in ext2_get_block only. ext3 uses i_truncate.
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 122) */
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 123) mutex_lock(&ei->truncate_mutex);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 124) if (!ei->i_block_alloc_info)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 125) ext2_init_block_alloc_info(inode);
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 126)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 127) if (ei->i_block_alloc_info){
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 128) struct ext2_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 129) rsv->rsv_goal_size = rsv_window_size;
acd1f04679803 (Chengguang Xu 2019-10-23 21:56:43 +0800 130) } else {
acd1f04679803 (Chengguang Xu 2019-10-23 21:56:43 +0800 131) ret = -ENOMEM;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 132) }
acd1f04679803 (Chengguang Xu 2019-10-23 21:56:43 +0800 133)
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 134) mutex_unlock(&ei->truncate_mutex);
2a79f17e4a641 (Al Viro 2011-12-09 08:06:57 -0500 135) mnt_drop_write_file(filp);
acd1f04679803 (Chengguang Xu 2019-10-23 21:56:43 +0800 136) return ret;
a686cd898bd99 (Martin J. Bligh 2007-10-16 23:30:46 -0700 137) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 138) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 139) return -ENOTTY;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 140) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 141) }
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 142)
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 143) #ifdef CONFIG_COMPAT
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 144) long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 145) {
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 146) /* These are just misnamed, they actually get/put from/to user an int */
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 147) switch (cmd) {
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 148) case EXT2_IOC32_GETVERSION:
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 149) cmd = EXT2_IOC_GETVERSION;
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 150) break;
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 151) case EXT2_IOC32_SETVERSION:
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 152) cmd = EXT2_IOC_SETVERSION;
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 153) break;
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 154) default:
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 155) return -ENOIOCTLCMD;
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 156) }
14f9f7b28e9f4 (Andi Kleen 2008-02-06 01:40:10 -0800 157) return ext2_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 158) }
e322ff07fb2d0 (David Howells 2006-08-29 19:06:20 +0100 159) #endif