• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/gpu/ion/compat_ion.c
3  *
4  * Copyright (C) 2013 Google, Inc.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16 
17 #include <linux/compat.h>
18 #include <linux/fs.h>
19 #include <linux/uaccess.h>
20 
21 #include "ion.h"
22 #include "compat_ion.h"
23 
24 /* See drivers/staging/android/uapi/ion.h for the definition of these structs */
25 struct compat_ion_allocation_data {
26 	compat_size_t len;
27 	compat_size_t align;
28 	compat_uint_t heap_id_mask;
29 	compat_uint_t flags;
30 	compat_int_t handle;
31 };
32 
33 struct compat_ion_custom_data {
34 	compat_uint_t cmd;
35 	compat_ulong_t arg;
36 };
37 
38 struct compat_ion_handle_data {
39 	compat_int_t handle;
40 };
41 
42 #define COMPAT_ION_IOC_ALLOC	_IOWR(ION_IOC_MAGIC, 0, \
43 				      struct compat_ion_allocation_data)
44 #define COMPAT_ION_IOC_FREE	_IOWR(ION_IOC_MAGIC, 1, \
45 				      struct compat_ion_handle_data)
46 #define COMPAT_ION_IOC_CUSTOM	_IOWR(ION_IOC_MAGIC, 6, \
47 				      struct compat_ion_custom_data)
48 
compat_get_ion_allocation_data(struct compat_ion_allocation_data __user * data32,struct ion_allocation_data __user * data)49 static int compat_get_ion_allocation_data(
50 			struct compat_ion_allocation_data __user *data32,
51 			struct ion_allocation_data __user *data)
52 {
53 	compat_size_t s;
54 	compat_uint_t u;
55 	compat_int_t i;
56 	int err;
57 
58 	err = get_user(s, &data32->len);
59 	err |= put_user(s, &data->len);
60 	err |= get_user(s, &data32->align);
61 	err |= put_user(s, &data->align);
62 	err |= get_user(u, &data32->heap_id_mask);
63 	err |= put_user(u, &data->heap_id_mask);
64 	err |= get_user(u, &data32->flags);
65 	err |= put_user(u, &data->flags);
66 	err |= get_user(i, &data32->handle);
67 	err |= put_user(i, &data->handle);
68 
69 	return err;
70 }
71 
compat_get_ion_handle_data(struct compat_ion_handle_data __user * data32,struct ion_handle_data __user * data)72 static int compat_get_ion_handle_data(
73 			struct compat_ion_handle_data __user *data32,
74 			struct ion_handle_data __user *data)
75 {
76 	compat_int_t i;
77 	int err;
78 
79 	err = get_user(i, &data32->handle);
80 	err |= put_user(i, &data->handle);
81 
82 	return err;
83 }
84 
compat_put_ion_allocation_data(struct compat_ion_allocation_data __user * data32,struct ion_allocation_data __user * data)85 static int compat_put_ion_allocation_data(
86 			struct compat_ion_allocation_data __user *data32,
87 			struct ion_allocation_data __user *data)
88 {
89 	compat_size_t s;
90 	compat_uint_t u;
91 	compat_int_t i;
92 	int err;
93 
94 	err = get_user(s, &data->len);
95 	err |= put_user(s, &data32->len);
96 	err |= get_user(s, &data->align);
97 	err |= put_user(s, &data32->align);
98 	err |= get_user(u, &data->heap_id_mask);
99 	err |= put_user(u, &data32->heap_id_mask);
100 	err |= get_user(u, &data->flags);
101 	err |= put_user(u, &data32->flags);
102 	err |= get_user(i, &data->handle);
103 	err |= put_user(i, &data32->handle);
104 
105 	return err;
106 }
107 
compat_get_ion_custom_data(struct compat_ion_custom_data __user * data32,struct ion_custom_data __user * data)108 static int compat_get_ion_custom_data(
109 			struct compat_ion_custom_data __user *data32,
110 			struct ion_custom_data __user *data)
111 {
112 	compat_uint_t cmd;
113 	compat_ulong_t arg;
114 	int err;
115 
116 	err = get_user(cmd, &data32->cmd);
117 	err |= put_user(cmd, &data->cmd);
118 	err |= get_user(arg, &data32->arg);
119 	err |= put_user(arg, &data->arg);
120 
121 	return err;
122 };
123 
compat_ion_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)124 long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
125 {
126 	long ret;
127 
128 	if (!filp->f_op || !filp->f_op->unlocked_ioctl)
129 		return -ENOTTY;
130 
131 	switch (cmd) {
132 	case COMPAT_ION_IOC_ALLOC:
133 	{
134 		struct compat_ion_allocation_data __user *data32;
135 		struct ion_allocation_data __user *data;
136 		int err;
137 
138 		data32 = compat_ptr(arg);
139 		data = compat_alloc_user_space(sizeof(*data));
140 		if (data == NULL)
141 			return -EFAULT;
142 
143 		err = compat_get_ion_allocation_data(data32, data);
144 		if (err)
145 			return err;
146 		ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC,
147 							(unsigned long)data);
148 		err = compat_put_ion_allocation_data(data32, data);
149 		return ret ? ret : err;
150 	}
151 	case COMPAT_ION_IOC_FREE:
152 	{
153 		struct compat_ion_handle_data __user *data32;
154 		struct ion_handle_data __user *data;
155 		int err;
156 
157 		data32 = compat_ptr(arg);
158 		data = compat_alloc_user_space(sizeof(*data));
159 		if (data == NULL)
160 			return -EFAULT;
161 
162 		err = compat_get_ion_handle_data(data32, data);
163 		if (err)
164 			return err;
165 
166 		return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE,
167 							(unsigned long)data);
168 	}
169 	case COMPAT_ION_IOC_CUSTOM: {
170 		struct compat_ion_custom_data __user *data32;
171 		struct ion_custom_data __user *data;
172 		int err;
173 
174 		data32 = compat_ptr(arg);
175 		data = compat_alloc_user_space(sizeof(*data));
176 		if (data == NULL)
177 			return -EFAULT;
178 
179 		err = compat_get_ion_custom_data(data32, data);
180 		if (err)
181 			return err;
182 
183 		return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM,
184 							(unsigned long)data);
185 	}
186 	case ION_IOC_SHARE:
187 	case ION_IOC_MAP:
188 	case ION_IOC_IMPORT:
189 	case ION_IOC_SYNC:
190 		return filp->f_op->unlocked_ioctl(filp, cmd,
191 						(unsigned long)compat_ptr(arg));
192 	default:
193 		return -ENOIOCTLCMD;
194 	}
195 }
196