【解決方法】エラー: 関数 ‘__vmalloc’ への引数が多すぎます

プログラミングQA


アップデート:

omar_mustafa@omar-mustafa-HP-Laptop-15-da1xxx:~/Downloads/ndiswrapper-1.63$ sudo make
make -C utils
make[1]: Entering directory '/home/omar_mustafa/Downloads/ndiswrapper-1.63/utils'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/omar_mustafa/Downloads/ndiswrapper-1.63/utils'
make -C driver
make[1]: Entering directory '/home/omar_mustafa/Downloads/ndiswrapper-1.63/driver'
make -C /usr/src/linux-headers-5.13.9-051309-generic M=/home/omar_mustafa/Downloads/ndiswrapper-1.63/driver
make[2]: Entering directory '/usr/src/linux-headers-5.13.9-051309-generic'
CC [M] /home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/crt.o
CC [M] /home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/hal.o
CC [M] /home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/iw_ndis.o
CC [M] /home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/loader.o
/home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/loader.c: In function ‘load_sys_files’:
/home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/loader.c:157:4: error: too many arguments to function ‘__vmalloc’
157 | __vmalloc(load_driver->sys_files[i].size,
| ^~~~~~~~~
In file included from ./include/asm-generic/io.h:911,
from ./arch/x86/include/asm/io.h:375,
from ./include/linux/scatterlist.h:9,
from ./include/linux/dma-mapping.h:10,
from ./include/linux/skbuff.h:31,
from ./include/net/net_namespace.h:38,
from ./include/linux/netdevice.h:37,
from /home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/ntoskernel.h:25,
from /home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/ndis.h:19,
from /home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/loader.c:16:
./include/linux/vmalloc.h:113:14: note: declared here
113 | extern void *__vmalloc(unsigned long size, gfp_t gfp_mask);
| ^~~~~~~~~
make[3]: *** [scripts/Makefile.build:273: /home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/loader.o] Error 1
make[2]: *** [Makefile:1859: /home/omar_mustafa/Downloads/ndiswrapper-1.63/driver] Error 2
make[2]: Leaving directory '/usr/src/linux-headers-5.13.9-051309-generic'
make[1]: *** [Makefile:183: modules] Error 2
make[1]: Leaving directory '/home/omar_mustafa/Downloads/ndiswrapper-1.63/driver'
make: *** [Makefile:23: driver] Error 2

こんにちは、C プログラムをコンパイルしようとしましたが、次のエラーが発生しました。

error: too many arguments to function ‘__vmalloc’
  157 |    __vmalloc(load_driver->sys_files[i].size,

問題は、「_vmalloc」が別のヘッダー ファイルから呼び出され、そこで次のように定義されていることです。

C++
extern void *__vmalloc(unsigned long size, gfp_t gfp_mask);

誰かが私を助けて、何が悪いのか教えてください??

私が試したこと:

関数宣言を C ファイルにコピーしましたが、同じエラーが発生しました

解決策 1

/home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/loader.c: In function ‘load_sys_files’:
/home/omar_mustafa/Downloads/ndiswrapper-1.63/driver/loader.c:157:4: error: too many arguments to function ‘__vmalloc’
157 | __vmalloc(load_driver->sys_files[i].size,
| ^~~~~~~~~

エラー メッセージを見てください。モジュール loader.c の 157 行が問題の原因です。 ソースを確認して、その理由を確認してください。

解決策 2

C++
  1  /*
  2   *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
  3   *
  4   *  This program is free software; you can redistribute it and/or modify
  5   *  it under the terms of the GNU General Public License as published by
  6   *  the Free Software Foundation; either version 2 of the License, or
  7   *  (at your option) any later version.
  8   *
  9   *  This program is distributed in the hope that it will be useful,
 10   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 11   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 12   *  GNU General Public License for more details.
 13   *
 14   */
 15  
 16  #include "ndis.h"
 17  #include "loader.h"
 18  #include "wrapndis.h"
 19  #include "pnp.h"
 20  
 21  #include <linux/module.h>
 22  #include <linux/kmod.h>
 23  #include <linux/miscdevice.h>
 24  #include <asm/uaccess.h>
 25  
 26  /*
 27    Network adapter: ClassGuid = {4d36e972-e325-11ce-bfc1-08002be10318}
 28    Network client: ClassGuid = {4d36e973-e325-11ce-bfc1-08002be10318}
 29    PCMCIA adapter: ClassGuid = {4d36e977-e325-11ce-bfc1-08002be10318}
 30    USB: ClassGuid = {36fc9e60-c465-11cf-8056-444553540000}
 31  */
 32  
 33  /* the indices used here must match macros WRAP_NDIS_DEVICE etc. */
 34  static struct guid class_guids[] = {
 35  	/* Network */
 36  	{ .data1 = 0x4d36e972, .data2 = 0xe325, .data3 = 0x11ce },
 37  	/* USB WDM */
 38  	{ .data1 = 0x36fc9e60, .data2 = 0xc465, .data3 = 0x11cf },
 39  	/* Bluetooth */
 40  	{ .data1 = 0xe0cbf06c, .data2 = 0xcd8b, .data3 = 0x4647 },
 41  	/* ivtcorporation.com's bluetooth device claims this is
 42  	 * bluetooth guid */
 43  	{ .data1 = 0xf12d3cf8, .data2 = 0xb11d, .data3 = 0x457e},
 44  };
 45  
 46  struct mutex loader_mutex;
 47  static struct completion loader_complete;
 48  
 49  static struct nt_list wrap_devices;
 50  static struct nt_list wrap_drivers;
 51  
 52  static int wrap_device_type(int data1)
 53  {
 54  	int i;
 55  	for (i = 0; i < ARRAY_SIZE(class_guids); i++)
 56  		if (data1 == class_guids[i].data1)
 57  			return i;
 58  	ERROR("unknown device: 0x%x\n", data1);
 59  	return -1;
 60  }
 61  
 62  /* load driver for given device, if not already loaded */
 63  struct wrap_driver *load_wrap_driver(struct wrap_device *wd)
 64  {
 65  	int ret;
 66  	struct nt_list *cur;
 67  	struct wrap_driver *wrap_driver;
 68  
 69  	ENTER1("device: %04X:%04X:%04X:%04X", wd->vendor, wd->device,
 70  	       wd->subvendor, wd->subdevice);
 71  	mutex_lock(&loader_mutex);
 72  	wrap_driver = NULL;
 73  	nt_list_for_each(cur, &wrap_drivers) {
 74  		wrap_driver = container_of(cur, struct wrap_driver, list);
 75  		if (!stricmp(wrap_driver->name, wd->driver_name)) {
 76  			TRACE1("driver %s already loaded", wrap_driver->name);
 77  			break;
 78  		} else
 79  			wrap_driver = NULL;
 80  	}
 81  	mutex_unlock(&loader_mutex);
 82  
 83  	if (!wrap_driver) {
 84  		char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DRIVER,
 85  #if DEBUG >= 1
 86  				"1",
 87  #else
 88  				"0",
 89  #endif
 90  				UTILS_VERSION, wd->driver_name,
 91  				wd->conf_file_name, NULL};
 92  		char *env[] = {NULL};
 93  
 94  		TRACE1("loading driver %s", wd->driver_name);
 95  		mutex_lock(&loader_mutex);
 96  		reinit_completion(&loader_complete);
 97  		ret = call_usermodehelper("/sbin/loadndisdriver", argv, env,
 98  					  UMH_WAIT_PROC);
 99  		if (ret) {
100  			mutex_unlock(&loader_mutex);
101  			ERROR("couldn't load driver %s; check system log "
102  			      "for messages from 'loadndisdriver'",
103  			      wd->driver_name);
104  			EXIT1(return NULL);
105  		}
106  		wait_for_completion(&loader_complete);
107  		TRACE1("%s", wd->driver_name);
108  		wrap_driver = NULL;
109  		nt_list_for_each(cur, &wrap_drivers) {
110  			wrap_driver = container_of(cur, struct wrap_driver,
111  						   list);
112  			if (!stricmp(wrap_driver->name, wd->driver_name)) {
113  				wd->driver = wrap_driver;
114  				break;
115  			} else
116  				wrap_driver = NULL;
117  		}
118  		mutex_unlock(&loader_mutex);
119  		if (wrap_driver)
120  			TRACE1("driver %s is loaded", wrap_driver->name);
121  		else
122  			ERROR("couldn't load driver '%s'", wd->driver_name);
123  	}
124  	EXIT1(return wrap_driver);
125  }
126  
127  /* load the driver files from userspace. */
128  static int load_sys_files(struct wrap_driver *driver,
129  			  struct load_driver *load_driver)
130  {
131  	int i, err;
132  
133  	TRACE1("num_pe_images = %d", load_driver->num_sys_files);
134  	TRACE1("loading driver: %s", load_driver->name);
135  	strncpy(driver->name, load_driver->name, sizeof(driver->name));
136  	driver->name[sizeof(driver->name)-1] = 0;
137  	TRACE1("driver: %s", driver->name);
138  	err = 0;
139  	driver->num_pe_images = 0;
140  	for (i = 0; i < load_driver->num_sys_files; i++) {
141  		struct pe_image *pe_image;
142  		pe_image = &driver->pe_images[driver->num_pe_images];
143  
144  		strncpy(pe_image->name, load_driver->sys_files[i].name,
145  			sizeof(pe_image->name));
146  		pe_image->name[sizeof(pe_image->name)-1] = 0;
147  		TRACE1("image size: %zu bytes", load_driver->sys_files[i].size);
148  
149  #ifdef CONFIG_X86_64
150  #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
151  	image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM);
152  #else
153  #ifdef PAGE_KERNEL_EXECUTABLE
154  		pe_image->image =
155  			__vmalloc(load_driver->sys_files[i].size,
156  				  GFP_KERNEL | __GFP_HIGHMEM,
157  				  PAGE_KERNEL_EXECUTABLE);
158  #elif defined PAGE_KERNEL_EXEC
159  		pe_image->image =
160  			__vmalloc(load_driver->sys_files[i].size,
161  				  GFP_KERNEL | __GFP_HIGHMEM,
162  				  PAGE_KERNEL_EXEC);
163  #else
164  #error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
165  #endif
166  #endif /* kernel 5.8 */
167  #else
168  		/* hate to play with kernel macros, but PAGE_KERNEL_EXEC is
169  		 * not available to modules! */
170  #ifdef cpu_has_nx
171  		if (cpu_has_nx)
172  			pe_image->image =
173  				__vmalloc(load_driver->sys_files[i].size,
174  					  GFP_KERNEL | __GFP_HIGHMEM,
175  					  __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
176  		else
177  			pe_image->image =
178  				vmalloc(load_driver->sys_files[i].size);
179  #else
180  			pe_image->image =
181  				vmalloc(load_driver->sys_files[i].size);
182  #endif
183  #endif
184  		if (!pe_image->image) {
185  			ERROR("couldn't allocate memory");
186  			err = -ENOMEM;
187  			break;
188  		}
189  		TRACE1("image is at %p", pe_image->image);
190  
191  		if (copy_from_user(pe_image->image,
192  				   load_driver->sys_files[i].data,
193  				   load_driver->sys_files[i].size)) {
194  			ERROR("couldn't load file %s",
195  			      load_driver->sys_files[i].name);
196  			err = -EFAULT;
197  			break;
198  		}
199  		pe_image->size = load_driver->sys_files[i].size;
200  		driver->num_pe_images++;
201  	}
202  
203  	if (!err && link_pe_images(driver->pe_images, driver->num_pe_images)) {
204  		ERROR("couldn't prepare driver '%s'", load_driver->name);
205  		err = -EINVAL;
206  	}
207  
208  	if (driver->num_pe_images < load_driver->num_sys_files || err) {
209  		for (i = 0; i < driver->num_pe_images; i++)
210  			if (driver->pe_images[i].image)
211  				vfree(driver->pe_images[i].image);
212  		driver->num_pe_images = 0;
213  		EXIT1(return err);
214  	} else
215  		EXIT1(return 0);
216  }
217  
218  struct wrap_bin_file *get_bin_file(char *bin_file_name)
219  {
220  	int i = 0;
221  	struct wrap_driver *driver, *cur;
222  
223  	ENTER1("%s", bin_file_name);
224  	mutex_lock(&loader_mutex);
225  	driver = NULL;
226  	nt_list_for_each_entry(cur, &wrap_drivers, list) {
227  		for (i = 0; i < cur->num_bin_files; i++)
228  			if (!stricmp(cur->bin_files[i].name, bin_file_name)) {
229  				driver = cur;
230  				break;
231  			}
232  		if (driver)
233  			break;
234  	}
235  	mutex_unlock(&loader_mutex);
236  	if (!driver) {
237  		TRACE1("couldn't find bin file '%s'", bin_file_name);
238  		return NULL;
239  	}
240  
241  	if (!driver->bin_files[i].data) {
242  		char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_BIN_FILE,
243  #if DEBUG >= 1
244  				"1",
245  #else
246  				"0",
247  #endif
248  				UTILS_VERSION, driver->name,
249  				driver->bin_files[i].name, NULL};
250  		char *env[] = {NULL};
251  		int ret;
252  
253  		TRACE1("loading bin file %s/%s", driver->name,
254  		       driver->bin_files[i].name);
255  		mutex_lock(&loader_mutex);
256  		reinit_completion(&loader_complete);
257  		ret = call_usermodehelper("/sbin/loadndisdriver", argv, env,
258  					  UMH_WAIT_PROC);
259  		if (ret) {
260  			mutex_unlock(&loader_mutex);
261  			ERROR("couldn't load file %s/%s; check system log "
262  			      "for messages from 'loadndisdriver' (%d)",
263  			      driver->name, driver->bin_files[i].name, ret);
264  			EXIT1(return NULL);
265  		}
266  		wait_for_completion(&loader_complete);
267  		mutex_unlock(&loader_mutex);
268  		if (!driver->bin_files[i].data) {
269  			WARNING("couldn't load binary file %s",
270  				driver->bin_files[i].name);
271  			EXIT1(return NULL);
272  		}
273  	}
274  	EXIT2(return &(driver->bin_files[i]));
275  }
276  
277  /* called with loader_mutex down */
278  static int add_bin_file(struct load_driver_file *driver_file)
279  {
280  	struct wrap_driver *driver, *cur;
281  	struct wrap_bin_file *bin_file;
282  	int i = 0;
283  
284  	driver = NULL;
285  	nt_list_for_each_entry(cur, &wrap_drivers, list) {
286  		for (i = 0; i < cur->num_bin_files; i++)
287  			if (!stricmp(cur->bin_files[i].name,
288  				     driver_file->name)) {
289  				driver = cur;
290  				break;
291  			}
292  		if (driver)
293  			break;
294  	}
295  	if (!driver) {
296  		ERROR("couldn't find %s", driver_file->name);
297  		return -EINVAL;
298  	}
299  	bin_file = &driver->bin_files[i];
300  	strncpy(bin_file->name, driver_file->name, sizeof(bin_file->name));
301  	bin_file->name[sizeof(bin_file->name)-1] = 0;
302  	bin_file->data = vmalloc(driver_file->size);
303  	if (!bin_file->data) {
304  		ERROR("couldn't allocate memory");
305  		return -ENOMEM;
306  	}
307  	bin_file->size = driver_file->size;
308  	if (copy_from_user(bin_file->data, driver_file->data, bin_file->size)) {
309  		ERROR("couldn't copy data");
310  		free_bin_file(bin_file);
311  		return -EFAULT;
312  	}
313  	return 0;
314  }
315  
316  void free_bin_file(struct wrap_bin_file *bin_file)
317  {
318  	TRACE2("unloading %s", bin_file->name);
319  	if (bin_file->data)
320  		vfree(bin_file->data);
321  	bin_file->data = NULL;
322  	bin_file->size = 0;
323  	EXIT2(return);
324  }
325  
326  /* load firmware files from userspace */
327  static int load_bin_files_info(struct wrap_driver *driver,
328  			       struct load_driver *load_driver)
329  {
330  	struct wrap_bin_file *bin_files;
331  	int i;
332  
333  	ENTER1("%s, %d", load_driver->name, load_driver->num_bin_files);
334  	driver->num_bin_files = 0;
335  	driver->bin_files = NULL;
336  	if (load_driver->num_bin_files == 0)
337  		EXIT1(return 0);
338  	bin_files = kzalloc(load_driver->num_bin_files * sizeof(*bin_files),
339  			    GFP_KERNEL);
340  	if (!bin_files) {
341  		ERROR("couldn't allocate memory");
342  		EXIT1(return -ENOMEM);
343  	}
344  
345  	for (i = 0; i < load_driver->num_bin_files; i++) {
346  		strncpy(bin_files[i].name, load_driver->bin_files[i].name,
347  			sizeof(bin_files[i].name));
348  		bin_files[i].name[sizeof(bin_files[i].name)-1] = 0;
349  		TRACE2("loaded bin file %s", bin_files[i].name);
350  	}
351  	driver->num_bin_files = load_driver->num_bin_files;
352  	driver->bin_files = bin_files;
353  	EXIT1(return 0);
354  }
355  
356  /* load settings for a device. called with loader_mutex down */
357  static int load_settings(struct wrap_driver *wrap_driver,
358  			 struct load_driver *load_driver)
359  {
360  	int i, num_settings;
361  
362  	ENTER1("%p, %p", wrap_driver, load_driver);
363  
364  	num_settings = 0;
365  	for (i = 0; i < load_driver->num_settings; i++) {
366  		struct load_device_setting *load_setting =
367  			&load_driver->settings[i];
368  		struct wrap_device_setting *setting;
369  		ULONG data1;
370  
371  		setting = kzalloc(sizeof(*setting), GFP_KERNEL);
372  		if (!setting) {
373  			ERROR("couldn't allocate memory");
374  			break;
375  		}
376  		strncpy(setting->name, load_setting->name,
377  			sizeof(setting->name));
378  		setting->name[sizeof(setting->name)-1] = 0;
379  		strncpy(setting->value, load_setting->value,
380  		       sizeof(setting->value));
381  		setting->value[sizeof(setting->value)-1] = 0;
382  		TRACE2("%p: %s=%s", setting, setting->name, setting->value);
383  
384  		if (strcmp(setting->name, "driver_version") == 0) {
385  			strncpy(wrap_driver->version, setting->value,
386  				sizeof(wrap_driver->version));
387  			wrap_driver->version[sizeof(wrap_driver->version)-1] = 0;
388  		} else if (strcmp(setting->name, "class_guid") == 0 &&
389  			   sscanf(setting->value, "%x", &data1) == 1) {
390  			wrap_driver->dev_type = wrap_device_type(data1);
391  			if (wrap_driver->dev_type < 0) {
392  				WARNING("unknown guid: %x", data1);
393  				wrap_driver->dev_type = 0;
394  			}
395  		}
396  		InsertTailList(&wrap_driver->settings, &setting->list);
397  		num_settings++;
398  	}
399  	/* it is not a fatal error if some settings couldn't be loaded */
400  	if (num_settings > 0)
401  		EXIT1(return 0);
402  	else
403  		EXIT1(return -EINVAL);
404  }
405  
406  void unload_wrap_device(struct wrap_device *wd)
407  {
408  	struct nt_list *cur;
409  	ENTER1("unloading device %p (%04X:%04X:%04X:%04X), driver %s", wd,
410  	       wd->vendor, wd->device, wd->subvendor, wd->subdevice,
411  	       wd->driver_name);
412  	mutex_lock(&loader_mutex);
413  	while ((cur = RemoveHeadList(&wd->settings))) {
414  		struct wrap_device_setting *setting;
415  		setting = container_of(cur, struct wrap_device_setting, list);
416  		kfree(setting);
417  	}
418  	RemoveEntryList(&wd->list);
419  	mutex_unlock(&loader_mutex);
420  	kfree(wd);
421  	EXIT1(return);
422  }
423  
424  /* should be called with loader_mutex down */
425  void unload_wrap_driver(struct wrap_driver *driver)
426  {
427  	int i;
428  	struct driver_object *drv_obj;
429  	struct nt_list *cur, *next;
430  
431  	ENTER1("unloading driver: %s (%p)", driver->name, driver);
432  	TRACE1("freeing %d images", driver->num_pe_images);
433  	drv_obj = driver->drv_obj;
434  	for (i = 0; i < driver->num_pe_images; i++)
435  		if (driver->pe_images[i].image) {
436  			TRACE1("freeing image at %p",
437  			       driver->pe_images[i].image);
438  			vfree(driver->pe_images[i].image);
439  		}
440  
441  	TRACE1("freeing %d bin files", driver->num_bin_files);
442  	for (i = 0; i < driver->num_bin_files; i++) {
443  		TRACE1("freeing image at %p", driver->bin_files[i].data);
444  		if (driver->bin_files[i].data)
445  			vfree(driver->bin_files[i].data);
446  	}
447  	kfree(driver->bin_files);
448  	RtlFreeUnicodeString(&drv_obj->name);
449  	RemoveEntryList(&driver->list);
450  	nt_list_for_each_safe(cur, next, &driver->settings) {
451  		struct wrap_device_setting *setting;
452  		struct ndis_configuration_parameter *param;
453  
454  		setting = container_of(cur, struct wrap_device_setting, list);
455  		TRACE2("%p", setting);
456  		param = setting->encoded;
457  		if (param) {
458  			TRACE2("%p", param);
459  			if (param->type == NdisParameterString)
460  				RtlFreeUnicodeString(¶m->data.string);
461  			ExFreePool(param);
462  		}
463  		kfree(setting);
464  	}
465  	/* this frees driver */
466  	free_custom_extensions(drv_obj->drv_ext);
467  	kfree(drv_obj->drv_ext);
468  	TRACE1("drv_obj: %p", drv_obj);
469  
470  	EXIT1(return);
471  }
472  
473  /* call the entry point of the driver */
474  static int start_wrap_driver(struct wrap_driver *driver)
475  {
476  	int i;
477  	NTSTATUS ret, res;
478  	struct driver_object *drv_obj;
479  	typeof(driver->pe_images[0].entry) entry;
480  
481  	ENTER1("%s", driver->name);
482  	drv_obj = driver->drv_obj;
483  	for (ret = res = 0, i = 0; i < driver->num_pe_images; i++)
484  		/* dlls are already started by loader */
485  		if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) {
486  			entry = driver->pe_images[i].entry;
487  			drv_obj->start = driver->pe_images[i].entry;
488  			drv_obj->driver_size = driver->pe_images[i].size;
489  			TRACE1("entry: %p, %p, drv_obj: %p",
490  			       entry, *entry, drv_obj);
491  			res = LIN2WIN2(entry, drv_obj, &drv_obj->name);
492  			ret |= res;
493  			TRACE1("entry returns %08X", res);
494  			break;
495  		}
496  	if (ret) {
497  		ERROR("driver initialization failed: %08X", ret);
498  		RtlFreeUnicodeString(&drv_obj->name);
499  		/* this frees ndis_driver */
500  		free_custom_extensions(drv_obj->drv_ext);
501  		kfree(drv_obj->drv_ext);
502  		TRACE1("drv_obj: %p", drv_obj);
503  		ObDereferenceObject(drv_obj);
504  		EXIT1(return -EINVAL);
505  	}
506  	EXIT1(return 0);
507  }
508  
509  /*
510   * add driver to list of loaded driver but make sure this driver is
511   * not loaded before. called with loader_mutex down
512   */
513  static int add_wrap_driver(struct wrap_driver *driver)
514  {
515  	struct wrap_driver *tmp;
516  
517  	ENTER1("name: %s", driver->name);
518  	nt_list_for_each_entry(tmp, &wrap_drivers, list) {
519  		if (stricmp(tmp->name, driver->name) == 0) {
520  			ERROR("cannot add duplicate driver");
521  			EXIT1(return -EBUSY);
522  		}
523  	}
524  	InsertHeadList(&wrap_drivers, &driver->list);
525  	EXIT1(return 0);
526  }
527  
528  /* load a driver from userspace and initialize it. called with
529   * loader_mutex down */
530  static int load_user_space_driver(struct load_driver *load_driver)
531  {
532  	struct driver_object *drv_obj;
533  	struct ansi_string ansi_reg;
534  	struct wrap_driver *wrap_driver = NULL;
535  
536  	ENTER1("%p", load_driver);
537  	drv_obj = allocate_object(sizeof(*drv_obj), OBJECT_TYPE_DRIVER, NULL);
538  	if (!drv_obj) {
539  		ERROR("couldn't allocate memory");
540  		EXIT1(return -ENOMEM);
541  	}
542  	TRACE1("drv_obj: %p", drv_obj);
543  	drv_obj->drv_ext = kzalloc(sizeof(*(drv_obj->drv_ext)), GFP_KERNEL);
544  	if (!drv_obj->drv_ext) {
545  		ERROR("couldn't allocate memory");
546  		ObDereferenceObject(drv_obj);
547  		EXIT1(return -ENOMEM);
548  	}
549  	InitializeListHead(&drv_obj->drv_ext->custom_ext);
550  	if (IoAllocateDriverObjectExtension(drv_obj,
551  					    (void *)WRAP_DRIVER_CLIENT_ID,
552  					    sizeof(*wrap_driver),
553  					    (void **)&wrap_driver) !=
554  	    STATUS_SUCCESS)
555  		EXIT1(return -ENOMEM);
556  	TRACE1("driver: %p", wrap_driver);
557  	memset(wrap_driver, 0, sizeof(*wrap_driver));
558  	InitializeListHead(&wrap_driver->list);
559  	InitializeListHead(&wrap_driver->settings);
560  	wrap_driver->drv_obj = drv_obj;
561  	RtlInitAnsiString(&ansi_reg, "/tmp");
562  	if (RtlAnsiStringToUnicodeString(&drv_obj->name, &ansi_reg, TRUE) !=
563  	    STATUS_SUCCESS) {
564  		ERROR("couldn't initialize registry path");
565  		free_custom_extensions(drv_obj->drv_ext);
566  		kfree(drv_obj->drv_ext);
567  		TRACE1("drv_obj: %p", drv_obj);
568  		ObDereferenceObject(drv_obj);
569  		EXIT1(return -EINVAL);
570  	}
571  	strncpy(wrap_driver->name, load_driver->name, sizeof(wrap_driver->name));
572  	wrap_driver->name[sizeof(wrap_driver->name)-1] = 0;
573  	if (load_sys_files(wrap_driver, load_driver) ||
574  	    load_bin_files_info(wrap_driver, load_driver) ||
575  	    load_settings(wrap_driver, load_driver) ||
576  	    start_wrap_driver(wrap_driver) ||
577  	    add_wrap_driver(wrap_driver)) {
578  		unload_wrap_driver(wrap_driver);
579  		ObDereferenceObject(drv_obj);
580  		EXIT1(return -EINVAL);
581  	} else {
582  		printk(KERN_INFO "%s: driver %s (%s) loaded\n",
583  		       DRIVER_NAME, wrap_driver->name, wrap_driver->version);
584  		add_taint(TAINT_PROPRIETARY_MODULE, LOCKDEP_NOW_UNRELIABLE);
585  		EXIT1(return 0);
586  	}
587  }
588  
589  static struct pci_device_id wrap_pci_id_table[] = {
590  	{
591  		.vendor = PCI_ANY_ID,
592  		.device = PCI_ANY_ID,
593  		.subvendor = PCI_ANY_ID,
594  		.subdevice = PCI_ANY_ID,
595  		.class = 0,
596  		.class_mask = 0,
597  		.driver_data = 0
598  	}
599  };
600  
601  static struct pci_driver wrap_pci_driver = {
602  	.name		= DRIVER_NAME,
603  	.id_table	= wrap_pci_id_table,
604  	.probe		= wrap_pnp_start_pci_device,
605  	.remove		= wrap_pnp_remove_pci_device,
606  	.suspend	= wrap_pnp_suspend_pci_device,
607  	.resume		= wrap_pnp_resume_pci_device,
608  };
609  
610  #ifdef ENABLE_USB
611  static struct usb_device_id wrap_usb_id_table[] = {
612  	{
613  		.driver_info = 1
614  	},
615  };
616  
617  static struct usb_driver wrap_usb_driver = {
618  	.name = DRIVER_NAME,
619  	.id_table = wrap_usb_id_table,
620  	.probe = wrap_pnp_start_usb_device,
621  	.disconnect = wrap_pnp_remove_usb_device,
622  	.suspend = wrap_pnp_suspend_usb_device,
623  	.resume = wrap_pnp_resume_usb_device,
624  };
625  #endif
626  
627  /* register drivers for pci and usb */
628  static void register_devices(void)
629  {
630  	int res;
631  
632  	res = pci_register_driver(&wrap_pci_driver);
633  	if (res < 0) {
634  		ERROR("couldn't register pci driver: %d", res);
635  		wrap_pci_driver.name = NULL;
636  	}
637  
638  #ifdef ENABLE_USB
639  	res = usb_register(&wrap_usb_driver);
640  	if (res < 0) {
641  		ERROR("couldn't register usb driver: %d", res);
642  		wrap_usb_driver.name = NULL;
643  	}
644  #endif
645  	EXIT1(return);
646  }
647  
648  static void unregister_devices(void)
649  {
650  	struct nt_list *cur, *next;
651  
652  	mutex_lock(&loader_mutex);
653  	nt_list_for_each_safe(cur, next, &wrap_devices) {
654  		struct wrap_device *wd;
655  		wd = container_of(cur, struct wrap_device, list);
656  		set_bit(HW_DISABLED, &wd->hw_status);
657  	}
658  	mutex_unlock(&loader_mutex);
659  
660  	if (wrap_pci_driver.name)
661  		pci_unregister_driver(&wrap_pci_driver);
662  #ifdef ENABLE_USB
663  	if (wrap_usb_driver.name)
664  		usb_deregister(&wrap_usb_driver);
665  #endif
666  }
667  
668  struct wrap_device *load_wrap_device(struct load_device *load_device)
669  {
670  	int ret;
671  	struct nt_list *cur;
672  	struct wrap_device *wd = NULL;
673  	char vendor[5], device[5], subvendor[5], subdevice[5], bus[5];
674  
675  	ENTER1("%04x, %04x, %04x, %04x", load_device->vendor,
676  	       load_device->device, load_device->subvendor,
677  	       load_device->subdevice);
678  	if (sprintf(vendor, "%04x", load_device->vendor) == 4 &&
679  	    sprintf(device, "%04x", load_device->device) == 4 &&
680  	    sprintf(subvendor, "%04x", load_device->subvendor) == 4 &&
681  	    sprintf(subdevice, "%04x", load_device->subdevice) == 4 &&
682  	    sprintf(bus, "%04x", load_device->bus) == 4) {
683  		char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DEVICE,
684  #if DEBUG >= 1
685  				"1",
686  #else
687  				"0",
688  #endif
689  				UTILS_VERSION, vendor, device,
690  				subvendor, subdevice, bus, NULL};
691  		char *env[] = {NULL};
692  		TRACE2("%s, %s, %s, %s, %s", vendor, device,
693  		       subvendor, subdevice, bus);
694  		mutex_lock(&loader_mutex);
695  		reinit_completion(&loader_complete);
696  		ret = call_usermodehelper("/sbin/loadndisdriver", argv, env,
697  					  UMH_WAIT_PROC);
698  		if (ret) {
699  			mutex_unlock(&loader_mutex);
700  			TRACE1("couldn't load device %04x:%04x; check system "
701  			       "log for messages from 'loadndisdriver'",
702  			       load_device->vendor, load_device->device);
703  			EXIT1(return NULL);
704  		}
705  		wait_for_completion(&loader_complete);
706  		wd = NULL;
707  		nt_list_for_each(cur, &wrap_devices) {
708  			wd = container_of(cur, struct wrap_device, list);
709  			TRACE2("%p, %04x, %04x, %04x, %04x", wd, wd->vendor,
710  			       wd->device, wd->subvendor, wd->subdevice);
711  			if (wd->vendor == load_device->vendor &&
712  			    wd->device == load_device->device)
713  				break;
714  			else
715  				wd = NULL;
716  		}
717  		mutex_unlock(&loader_mutex);
718  	} else
719  		wd = NULL;
720  	EXIT1(return wd);
721  }
722  
723  struct wrap_device *get_wrap_device(void *dev, int bus)
724  {
725  	struct nt_list *cur;
726  	struct wrap_device *wd;
727  
728  	mutex_lock(&loader_mutex);
729  	wd = NULL;
730  	nt_list_for_each(cur, &wrap_devices) {
731  		wd = container_of(cur, struct wrap_device, list);
732  		if (bus == WRAP_PCI_BUS &&
733  		    wrap_is_pci_bus(wd->dev_bus) && wd->pci.pdev == dev)
734  			break;
735  		else if (bus == WRAP_USB_BUS &&
736  			 wrap_is_usb_bus(wd->dev_bus) && wd->usb.udev == dev)
737  			break;
738  		else
739  			wd = NULL;
740  	}
741  	mutex_unlock(&loader_mutex);
742  	return wd;
743  }
744  
745  /* called with loader_mutex is down */
746  static long wrapper_ioctl(struct file *file, unsigned int cmd,
747  			  unsigned long arg)
748  {
749  	struct load_driver *load_driver;
750  	struct load_device load_device;
751  	struct load_driver_file load_bin_file;
752  	int ret;
753  	void __user *addr = (void __user *)arg;
754  
755  	ENTER1("cmd: 0x%x", cmd);
756  
757  	ret = 0;
758  	switch (cmd) {
759  	case WRAP_IOCTL_LOAD_DEVICE:
760  		if (copy_from_user(&load_device, addr, sizeof(load_device))) {
761  			ret = -EFAULT;
762  			break;
763  		}
764  		TRACE2("%04x, %04x, %04x, %04x", load_device.vendor,
765  		       load_device.device, load_device.subvendor,
766  		       load_device.subdevice);
767  		if (load_device.vendor) {
768  			struct wrap_device *wd;
769  			wd = kzalloc(sizeof(*wd), GFP_KERNEL);
770  			if (!wd) {
771  				ret = -ENOMEM;
772  				break;
773  			}
774  			InitializeListHead(&wd->settings);
775  			wd->dev_bus = WRAP_BUS(load_device.bus);
776  			wd->vendor = load_device.vendor;
777  			wd->device = load_device.device;
778  			wd->subvendor = load_device.subvendor;
779  			wd->subdevice = load_device.subdevice;
780  			strncpy(wd->conf_file_name, load_device.conf_file_name,
781  				sizeof(wd->conf_file_name));
782  			wd->conf_file_name[sizeof(wd->conf_file_name)-1] = 0;
783  			strncpy(wd->driver_name, load_device.driver_name,
784  			       sizeof(wd->driver_name));
785  			wd->driver_name[sizeof(wd->driver_name)-1] = 0;
786  			InsertHeadList(&wrap_devices, &wd->list);
787  			ret = 0;
788  		} else
789  			ret = -EINVAL;
790  		break;
791  	case WRAP_IOCTL_LOAD_DRIVER:
792  		TRACE1("loading driver at %p", addr);
793  		load_driver = vmalloc(sizeof(*load_driver));
794  		if (!load_driver) {
795  			ret = -ENOMEM;
796  			break;
797  		}
798  		if (copy_from_user(load_driver, addr, sizeof(*load_driver)))
799  			ret = -EFAULT;
800  		else
801  			ret = load_user_space_driver(load_driver);
802  		vfree(load_driver);
803  		break;
804  	case WRAP_IOCTL_LOAD_BIN_FILE:
805  		if (copy_from_user(&load_bin_file, addr, sizeof(load_bin_file)))
806  			ret = -EFAULT;
807  		else
808  			ret = add_bin_file(&load_bin_file);
809  		break;
810  	default:
811  		ERROR("unknown ioctl 0x%x", cmd);
812  		ret = -EINVAL;
813  		break;
814  	}
815  	complete(&loader_complete);
816  	EXIT1(return ret);
817  }
818  
819  #ifdef CONFIG_COMPAT
820  static int copy_load_driver_file32(struct load_driver_file *k,
821  				   struct load_driver_file32 __user *u)
822  {
823  	u32 data;
824  
825  	if (copy_from_user(&k->driver_name, &u->driver_name,
826  			   sizeof(u->driver_name) + sizeof(u->name)))
827  		return -EFAULT;
828  
829  	if (get_user(k->size, &u->size))
830  		return -EFAULT;
831  	if (get_user(data, &u->data))
832  		return -EFAULT;
833  
834  	k->data = (void __user *)(unsigned long)data;
835  	return 0;
836  }
837  
838  static int copy_load_driver32(struct load_driver *k,
839  			      struct load_driver32 __user *u)
840  {
841  	int i;
842  
843  	if (copy_from_user(&k->name, &u->name,
844  			   sizeof(u->name) + sizeof(u->conf_file_name)))
845  		return -EFAULT;
846  
847  	if (get_user(k->num_sys_files, &u->num_sys_files))
848  		return -EFAULT;
849  
850  	for (i = 0; i < k->num_sys_files; i++)
851  		if (copy_load_driver_file32(&k->sys_files[i], &u->sys_files[i]))
852  			return -EFAULT;
853  
854  	if (get_user(k->num_settings, &u->num_settings))
855  		return -EFAULT;
856  
857  	if (copy_from_user(&k->settings, &u->settings,
858  			   sizeof(u->settings[0]) * k->num_settings))
859  		return -EFAULT;
860  
861  	if (get_user(k->num_bin_files, &u->num_bin_files))
862  		return -EFAULT;
863  
864  	for (i = 0; i < k->num_bin_files; i++)
865  		if (copy_load_driver_file32(&k->bin_files[i], &u->bin_files[i]))
866  			return -EFAULT;
867  
868  	return 0;
869  }
870  
871  static long wrapper_ioctl_compat(struct file *file, unsigned int cmd,
872  				 unsigned long arg)
873  {
874  	int ret = 0;
875  	void __user *addr = (void __user *)arg;
876  	struct load_driver *kdriver;
877  	struct load_driver32 __user *udriver = addr;
878  	struct load_driver_file kfile;
879  	struct load_driver_file32 __user *ufile = addr;
880  
881  	ENTER1("cmd: 0x%x", cmd);
882  
883  	switch (cmd) {
884  	case WRAP_IOCTL_LOAD_DEVICE32:
885  		return wrapper_ioctl(file, WRAP_IOCTL_LOAD_DEVICE, arg);
886  	case WRAP_IOCTL_LOAD_DRIVER32:
887  		TRACE1("loading driver at %p", addr);
888  		kdriver = vmalloc(sizeof(*kdriver));
889  		if (!kdriver) {
890  			ret = -ENOMEM;
891  			break;
892  		}
893  
894  		ret = copy_load_driver32(kdriver, udriver);
895  		if (!ret)
896  			ret = load_user_space_driver(kdriver);
897  
898  		vfree(kdriver);
899  		break;
900  	case WRAP_IOCTL_LOAD_BIN_FILE32:
901  		ret = copy_load_driver_file32(&kfile, ufile);
902  		if (ret)
903  			break;
904  
905  		ret = add_bin_file(&kfile);
906  		break;
907  	default:
908  		ERROR("unknown ioctl 0x%x", cmd);
909  		ret = -EINVAL;
910  		break;
911  	}
912  	complete(&loader_complete);
913  	EXIT1(return ret);
914  }
915  #endif
916  
917  static int wrapper_ioctl_release(struct inode *inode, struct file *file)
918  {
919  	ENTER1("");
920  	complete(&loader_complete);
921  	return 0;
922  }
923  
924  static struct file_operations wrapper_fops = {
925  	.owner		= THIS_MODULE,
926  	.unlocked_ioctl	= wrapper_ioctl,
927  #ifdef CONFIG_COMPAT
928  	.compat_ioctl	= wrapper_ioctl_compat,
929  #endif
930  	.release	= wrapper_ioctl_release,
931  };
932  
933  static struct miscdevice wrapper_misc = {
934  	.name	= DRIVER_NAME,
935  	.minor	= MISC_DYNAMIC_MINOR,
936  	.fops	= &wrapper_fops
937  };
938  
939  int loader_init(void)
940  {
941  	int err;
942  
943  	InitializeListHead(&wrap_drivers);
944  	InitializeListHead(&wrap_devices);
945  	mutex_init(&loader_mutex);
946  	init_completion(&loader_complete);
947  	if ((err = misc_register(&wrapper_misc)) < 0) {
948  		ERROR("couldn't register module (%d)", err);
949  		unregister_devices();
950  		EXIT1(return err);
951  	}
952  	register_devices();
953  	EXIT1(return 0);
954  }
955  
956  void loader_exit(void)
957  {
958  	struct nt_list *cur, *next;
959  
960  	ENTER1("");
961  	misc_deregister(&wrapper_misc);
962  	unregister_devices();
963  	mutex_lock(&loader_mutex);
964  	nt_list_for_each_safe(cur, next, &wrap_drivers) {
965  		struct wrap_driver *driver;
966  		driver = container_of(cur, struct wrap_driver, list);
967  		unload_wrap_driver(driver);
968  	}
969  	mutex_unlock(&loader_mutex);
970  	EXIT1(return);
971  }

コメント

タイトルとURLをコピーしました