3030#define IOCTL_MBOX_PROPERTY32 _IOWR(VCIO_IOC_MAGIC, 0, compat_uptr_t)
3131#endif
3232
33+ /* Tags permitted via /dev/vcio_provisioning. */
34+ static const u32 vcio_provisioning_tags [] = {
35+ 0x00038021 , /* SET_CUSTOMER_OTP */
36+ 0x00038024 , /* SET_USER_OTP */
37+ 0x00038082 , /* SET_CUSTOMER_ETHER_MAC_OTP */
38+ 0x00038083 , /* SET_CUSTOMER_WIFI_MAC_OTP */
39+ 0x00038084 , /* SET_CUSTOMER_BT_MAC_OTP */
40+ 0x00030085 , /* TST_MAC_OTP */
41+ 0x00030086 , /* SET_CUSTOMER_OTP_LOCK */
42+ };
43+
44+ /* Tags permitted via /dev/vcio_ab. */
45+ static const u32 vcio_ab_tags [] = {
46+ 0x00030048 , /* SET_NOTIFY_REBOOT */
47+ 0x00030057 , /* SET_GLOBAL_RESET */
48+ 0x00030064 , /* GET_REBOOT_FLAGS */
49+ 0x00038064 , /* SET_REBOOT_FLAGS */
50+ 0x0003008b , /* GET_REBOOT_ORDER */
51+ 0x0003808b , /* SET_REBOOT_ORDER */
52+ 0x0003008c , /* GET_REBOOT_ARG */
53+ 0x0003808c , /* SET_REBOOT_ARG */
54+ 0x0003008d , /* GET_BOOT_COUNT */
55+ 0x0003808d , /* SET_BOOT_COUNT */
56+ };
57+
58+ /* Tags permitted via /dev/vcio_gencmd. */
59+ static const u32 vcio_gencmd_tags [] = {
60+ 0x00030080 , /* GET_GENCMD_RESULT */
61+ };
62+
63+ /* Tags permitted via /dev/vcio_crypto. */
64+ static const u32 vcio_crypto_tags [] = {
65+ 0x0003008e , /* GET_CRYPTO_LAST_ERROR */
66+ 0x0003008f , /* GET_CRYPTO_NUM_OTP_KEYS */
67+ 0x00030090 , /* GET_CRYPTO_KEY_STATUS */
68+ 0x00038090 , /* SET_CRYPTO_KEY_STATUS */
69+ 0x00030091 , /* GET_CRYPTO_ECDSA_SIGN */
70+ 0x00030092 , /* GET_CRYPTO_HMAC_SHA256 */
71+ 0x00030093 , /* GET_CRYPTO_PUBLIC_KEY */
72+ 0x00030094 , /* GET_CRYPTO_PRIVATE_KEY */
73+ 0x00030095 , /* GET_CRYPTO_GEN_ECDSA */
74+ };
75+
76+ struct vcio_group {
77+ const char * name ;
78+ const u32 * tags ;
79+ size_t num_tags ;
80+ };
81+
82+ #define VCIO_GROUP (suffix ) { \
83+ .name = "vcio_" #suffix, \
84+ .tags = vcio_ ## suffix ## _tags, \
85+ .num_tags = ARRAY_SIZE(vcio_ ## suffix ## _tags), \
86+ }
87+
88+ static const struct vcio_group vcio_groups [] = {
89+ VCIO_GROUP (provisioning ),
90+ VCIO_GROUP (ab ),
91+ VCIO_GROUP (gencmd ),
92+ VCIO_GROUP (crypto ),
93+ };
94+
95+ struct vcio_dev {
96+ struct miscdevice misc_dev ;
97+ struct rpi_firmware * fw ;
98+ const u32 * allowed_tags ;
99+ size_t num_allowed_tags ;
100+ };
101+
33102struct vcio_data {
34103 struct rpi_firmware * fw ;
35- struct miscdevice misc_dev ;
104+ struct vcio_dev vcio ;
105+ struct vcio_dev groups [ARRAY_SIZE (vcio_groups )];
36106};
37107
38- static int vcio_user_property_list (struct vcio_data * vcio , void * user )
108+ static bool vcio_tag_allowed (const struct vcio_dev * vdev , u32 tag )
109+ {
110+ size_t i ;
111+
112+ if (!vdev -> allowed_tags )
113+ return true;
114+
115+ for (i = 0 ; i < vdev -> num_allowed_tags ; i ++ )
116+ if (vdev -> allowed_tags [i ] == tag )
117+ return true;
118+
119+ return false;
120+ }
121+
122+ static int vcio_check_tags (const struct vcio_dev * vdev , const u32 * buf ,
123+ size_t size )
124+ {
125+ size_t offset = 8 ; /* skip total size and status words */
126+
127+ if (!vdev -> allowed_tags )
128+ return 0 ;
129+
130+ while (offset + 12 <= size ) {
131+ u32 tag = buf [offset / 4 ];
132+ u32 val_size ;
133+
134+ if (tag == 0 )
135+ return 0 ;
136+
137+ if (!vcio_tag_allowed (vdev , tag )) {
138+ pr_warn_ratelimited ("%s: tag 0x%08x not permitted\n" ,
139+ vdev -> misc_dev .name , tag );
140+ return - EPERM ;
141+ }
142+
143+ val_size = buf [offset / 4 + 1 ];
144+ offset += 12 + ALIGN (val_size , 4 );
145+
146+ if (offset < 12 || offset > size )
147+ return - EINVAL ;
148+ }
149+
150+ return 0 ;
151+ }
152+
153+ static int vcio_user_property_list (struct vcio_dev * vdev , void * user )
39154{
40155 u32 * buf , size ;
41156 int ret ;
@@ -44,6 +159,9 @@ static int vcio_user_property_list(struct vcio_data *vcio, void *user)
44159 if (copy_from_user (& size , user , sizeof (size )))
45160 return - EFAULT ;
46161
162+ if (size < 12 )
163+ return - EINVAL ;
164+
47165 buf = kmalloc (size , GFP_KERNEL );
48166 if (!buf )
49167 return - ENOMEM ;
@@ -53,8 +171,14 @@ static int vcio_user_property_list(struct vcio_data *vcio, void *user)
53171 return - EFAULT ;
54172 }
55173
174+ ret = vcio_check_tags (vdev , buf , size );
175+ if (ret ) {
176+ kfree (buf );
177+ return ret ;
178+ }
179+
56180 /* Strip off protocol encapsulation */
57- ret = rpi_firmware_property_list (vcio -> fw , & buf [2 ], size - 12 );
181+ ret = rpi_firmware_property_list (vdev -> fw , & buf [2 ], size - 12 );
58182 if (ret ) {
59183 kfree (buf );
60184 return ret ;
@@ -86,12 +210,12 @@ static int vcio_device_release(struct inode *inode, struct file *file)
86210static long vcio_device_ioctl (struct file * file , unsigned int ioctl_num ,
87211 unsigned long ioctl_param )
88212{
89- struct vcio_data * vcio = container_of (file -> private_data ,
90- struct vcio_data , misc_dev );
213+ struct vcio_dev * vdev = container_of (file -> private_data ,
214+ struct vcio_dev , misc_dev );
91215
92216 switch (ioctl_num ) {
93217 case IOCTL_MBOX_PROPERTY :
94- return vcio_user_property_list (vcio , (void * )ioctl_param );
218+ return vcio_user_property_list (vdev , (void * )ioctl_param );
95219 default :
96220 pr_err ("unknown ioctl: %x\n" , ioctl_num );
97221 return - EINVAL ;
@@ -102,12 +226,12 @@ static long vcio_device_ioctl(struct file *file, unsigned int ioctl_num,
102226static long vcio_device_compat_ioctl (struct file * file , unsigned int ioctl_num ,
103227 unsigned long ioctl_param )
104228{
105- struct vcio_data * vcio = container_of (file -> private_data ,
106- struct vcio_data , misc_dev );
229+ struct vcio_dev * vdev = container_of (file -> private_data ,
230+ struct vcio_dev , misc_dev );
107231
108232 switch (ioctl_num ) {
109233 case IOCTL_MBOX_PROPERTY32 :
110- return vcio_user_property_list (vcio , compat_ptr (ioctl_param ));
234+ return vcio_user_property_list (vdev , compat_ptr (ioctl_param ));
111235 default :
112236 pr_err ("unknown ioctl: %x\n" , ioctl_num );
113237 return - EINVAL ;
@@ -124,13 +248,30 @@ const struct file_operations vcio_fops = {
124248 .release = vcio_device_release ,
125249};
126250
251+ static int vcio_register (struct device * dev , struct vcio_dev * vdev ,
252+ struct rpi_firmware * fw , const char * name ,
253+ const u32 * allowed_tags , size_t num_allowed_tags )
254+ {
255+ vdev -> fw = fw ;
256+ vdev -> allowed_tags = allowed_tags ;
257+ vdev -> num_allowed_tags = num_allowed_tags ;
258+ vdev -> misc_dev .fops = & vcio_fops ;
259+ vdev -> misc_dev .minor = MISC_DYNAMIC_MINOR ;
260+ vdev -> misc_dev .name = name ;
261+ vdev -> misc_dev .parent = dev ;
262+
263+ return misc_register (& vdev -> misc_dev );
264+ }
265+
127266static int vcio_probe (struct platform_device * pdev )
128267{
129268 struct device * dev = & pdev -> dev ;
130269 struct device_node * np = dev -> of_node ;
131270 struct device_node * fw_node ;
132271 struct rpi_firmware * fw ;
133272 struct vcio_data * vcio ;
273+ size_t i ;
274+ int ret ;
134275
135276 fw_node = of_get_parent (np );
136277 if (!fw_node ) {
@@ -143,24 +284,43 @@ static int vcio_probe(struct platform_device *pdev)
143284 if (!fw )
144285 return - EPROBE_DEFER ;
145286
146- vcio = devm_kzalloc (dev , sizeof (struct vcio_data ), GFP_KERNEL );
287+ vcio = devm_kzalloc (dev , sizeof (* vcio ), GFP_KERNEL );
147288 if (!vcio )
148289 return - ENOMEM ;
149290
150291 vcio -> fw = fw ;
151- vcio -> misc_dev .fops = & vcio_fops ;
152- vcio -> misc_dev .minor = MISC_DYNAMIC_MINOR ;
153- vcio -> misc_dev .name = "vcio" ;
154- vcio -> misc_dev .parent = dev ;
292+ platform_set_drvdata (pdev , vcio );
293+
294+ ret = vcio_register (dev , & vcio -> vcio , fw , "vcio" , NULL , 0 );
295+ if (ret )
296+ return ret ;
155297
156- return misc_register (& vcio -> misc_dev );
298+ for (i = 0 ; i < ARRAY_SIZE (vcio_groups ); i ++ ) {
299+ const struct vcio_group * g = & vcio_groups [i ];
300+
301+ ret = vcio_register (dev , & vcio -> groups [i ], fw , g -> name ,
302+ g -> tags , g -> num_tags );
303+ if (ret )
304+ goto err_groups ;
305+ }
306+
307+ return 0 ;
308+
309+ err_groups :
310+ while (i -- )
311+ misc_deregister (& vcio -> groups [i ].misc_dev );
312+ misc_deregister (& vcio -> vcio .misc_dev );
313+ return ret ;
157314}
158315
159316static void vcio_remove (struct platform_device * pdev )
160317{
161- struct device * dev = & pdev -> dev ;
318+ struct vcio_data * vcio = platform_get_drvdata (pdev );
319+ size_t i = ARRAY_SIZE (vcio_groups );
162320
163- misc_deregister (dev_get_drvdata (dev ));
321+ while (i -- )
322+ misc_deregister (& vcio -> groups [i ].misc_dev );
323+ misc_deregister (& vcio -> vcio .misc_dev );
164324}
165325
166326static const struct of_device_id vcio_ids [] = {
0 commit comments