1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Pioctl operations for Coda. |
4 | * Original version: (C) 1996 Peter Braam |
5 | * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University |
6 | * |
7 | * Carnegie Mellon encourages users of this code to contribute improvements |
8 | * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>. |
9 | */ |
10 | |
11 | #include <linux/types.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/time.h> |
14 | #include <linux/fs.h> |
15 | #include <linux/stat.h> |
16 | #include <linux/errno.h> |
17 | #include <linux/string.h> |
18 | #include <linux/namei.h> |
19 | #include <linux/module.h> |
20 | #include <linux/uaccess.h> |
21 | |
22 | #include <linux/coda.h> |
23 | #include "coda_psdev.h" |
24 | #include "coda_linux.h" |
25 | |
26 | /* pioctl ops */ |
27 | static int coda_ioctl_permission(struct mnt_idmap *idmap, |
28 | struct inode *inode, int mask); |
29 | static long coda_pioctl(struct file *filp, unsigned int cmd, |
30 | unsigned long user_data); |
31 | |
32 | /* exported from this file */ |
33 | const struct inode_operations coda_ioctl_inode_operations = { |
34 | .permission = coda_ioctl_permission, |
35 | .setattr = coda_setattr, |
36 | }; |
37 | |
38 | const struct file_operations coda_ioctl_operations = { |
39 | .unlocked_ioctl = coda_pioctl, |
40 | .llseek = noop_llseek, |
41 | }; |
42 | |
43 | /* the coda pioctl inode ops */ |
44 | static int coda_ioctl_permission(struct mnt_idmap *idmap, |
45 | struct inode *inode, int mask) |
46 | { |
47 | return (mask & MAY_EXEC) ? -EACCES : 0; |
48 | } |
49 | |
50 | static long coda_pioctl(struct file *filp, unsigned int cmd, |
51 | unsigned long user_data) |
52 | { |
53 | struct path path; |
54 | int error; |
55 | struct PioctlData data; |
56 | struct inode *inode = file_inode(f: filp); |
57 | struct inode *target_inode = NULL; |
58 | struct coda_inode_info *cnp; |
59 | |
60 | /* get the Pioctl data arguments from user space */ |
61 | if (copy_from_user(to: &data, from: (void __user *)user_data, n: sizeof(data))) |
62 | return -EINVAL; |
63 | |
64 | /* |
65 | * Look up the pathname. Note that the pathname is in |
66 | * user memory, and namei takes care of this |
67 | */ |
68 | error = user_path_at(AT_FDCWD, name: data.path, |
69 | flags: data.follow ? LOOKUP_FOLLOW : 0, path: &path); |
70 | if (error) |
71 | return error; |
72 | |
73 | target_inode = d_inode(dentry: path.dentry); |
74 | |
75 | /* return if it is not a Coda inode */ |
76 | if (target_inode->i_sb != inode->i_sb) { |
77 | error = -EINVAL; |
78 | goto out; |
79 | } |
80 | |
81 | /* now proceed to make the upcall */ |
82 | cnp = ITOC(inode: target_inode); |
83 | |
84 | error = venus_pioctl(sb: inode->i_sb, fid: &(cnp->c_fid), cmd, data: &data); |
85 | out: |
86 | path_put(&path); |
87 | return error; |
88 | } |
89 | |