compat_ion.c revision e1d855b02f5ac4c3a6cbeaa253958b2708826b9f
1/*
2 * drivers/staging/android/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 */
25struct 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
33struct compat_ion_custom_data {
34	compat_uint_t cmd;
35	compat_ulong_t arg;
36};
37
38#define COMPAT_ION_IOC_ALLOC	_IOWR(ION_IOC_MAGIC, 0, \
39				      struct compat_ion_allocation_data)
40#define COMPAT_ION_IOC_FREE	_IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
41#define COMPAT_ION_IOC_CUSTOM	_IOWR(ION_IOC_MAGIC, 6, \
42				      struct compat_ion_custom_data)
43
44static int compat_get_ion_allocation_data(
45			struct compat_ion_allocation_data __user *data32,
46			struct ion_allocation_data __user *data)
47{
48	compat_size_t s;
49	compat_uint_t u;
50	compat_int_t i;
51	int err;
52
53	err = get_user(s, &data32->len);
54	err |= put_user(s, &data->len);
55	err |= get_user(s, &data32->align);
56	err |= put_user(s, &data->align);
57	err |= get_user(u, &data32->heap_id_mask);
58	err |= put_user(u, &data->heap_id_mask);
59	err |= get_user(u, &data32->flags);
60	err |= put_user(u, &data->flags);
61	err |= get_user(i, &data32->handle);
62	err |= put_user(i, &data->handle);
63
64	return err;
65}
66
67static int compat_put_ion_allocation_data(
68			struct compat_ion_allocation_data __user *data32,
69			struct ion_allocation_data __user *data)
70{
71	compat_size_t s;
72	compat_uint_t u;
73	compat_int_t i;
74	int err;
75
76	err = get_user(s, &data->len);
77	err |= put_user(s, &data32->len);
78	err |= get_user(s, &data->align);
79	err |= put_user(s, &data32->align);
80	err |= get_user(u, &data->heap_id_mask);
81	err |= put_user(u, &data32->heap_id_mask);
82	err |= get_user(u, &data->flags);
83	err |= put_user(u, &data32->flags);
84	err |= get_user(i, &data->handle);
85	err |= put_user(i, &data32->handle);
86
87	return err;
88}
89
90static int compat_get_ion_custom_data(
91			struct compat_ion_custom_data __user *data32,
92			struct ion_custom_data __user *data)
93{
94	compat_uint_t cmd;
95	compat_ulong_t arg;
96	int err;
97
98	err = get_user(cmd, &data32->cmd);
99	err |= put_user(cmd, &data->cmd);
100	err |= get_user(arg, &data32->arg);
101	err |= put_user(arg, &data->arg);
102
103	return err;
104};
105
106long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
107{
108	long ret;
109
110	if (!filp->f_op || !filp->f_op->unlocked_ioctl)
111		return -ENOTTY;
112
113	switch (cmd) {
114	case COMPAT_ION_IOC_ALLOC:
115	{
116		struct compat_ion_allocation_data __user *data32;
117		struct ion_allocation_data __user *data;
118		int err;
119
120		data32 = compat_ptr(arg);
121		data = compat_alloc_user_space(sizeof(*data));
122		if (data == NULL)
123			return -EFAULT;
124
125		err = compat_get_ion_allocation_data(data32, data);
126		if (err)
127			return err;
128		ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC,
129							(unsigned long)data);
130		err = compat_put_ion_allocation_data(data32, data);
131		return ret ? ret : err;
132	}
133	case COMPAT_ION_IOC_FREE:
134	{
135		struct compat_ion_allocation_data __user *data32;
136		struct ion_allocation_data __user *data;
137		int err;
138
139		data32 = compat_ptr(arg);
140		data = compat_alloc_user_space(sizeof(*data));
141		if (data == NULL)
142			return -EFAULT;
143
144		err = compat_get_ion_allocation_data(data32, data);
145		if (err)
146			return err;
147
148		return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE,
149							(unsigned long)data);
150	}
151	case COMPAT_ION_IOC_CUSTOM: {
152		struct compat_ion_custom_data __user *data32;
153		struct ion_custom_data __user *data;
154		int err;
155
156		data32 = compat_ptr(arg);
157		data = compat_alloc_user_space(sizeof(*data));
158		if (data == NULL)
159			return -EFAULT;
160
161		err = compat_get_ion_custom_data(data32, data);
162		if (err)
163			return err;
164
165		return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM,
166							(unsigned long)data);
167	}
168	case ION_IOC_SHARE:
169	case ION_IOC_MAP:
170	case ION_IOC_IMPORT:
171	case ION_IOC_SYNC:
172		return filp->f_op->unlocked_ioctl(filp, cmd,
173						(unsigned long)compat_ptr(arg));
174	default:
175		return -ENOIOCTLCMD;
176	}
177}
178