Blame view

drivers/pci/syscall.c 2.68 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
  /*
   *	pci_syscall.c
   *
   * For architectures where we want to allow direct access
   * to the PCI config stuff - it would probably be preferable
   * on PCs too, but there people just do it by hand with the
   * magic northbridge registers..
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
  #include <linux/errno.h>
  #include <linux/pci.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
  #include <linux/syscalls.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
13
  #include <linux/uaccess.h>
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
14
  #include "pci.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15

c4ea37c26   Heiko Carstens   [CVE-2009-0029] S...
16
17
  SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn,
  		unsigned long, off, unsigned long, len, void __user *, buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
  {
  	struct pci_dev *dev;
  	u8 byte;
  	u16 word;
  	u32 dword;
e4585da22   Alan Cox   pci syscall.c: Sw...
23
24
  	long err;
  	long cfg_ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  	if (!capable(CAP_SYS_ADMIN))
e4585da22   Alan Cox   pci syscall.c: Sw...
27
  		return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
  
  	err = -ENODEV;
e4585da22   Alan Cox   pci syscall.c: Sw...
30
  	dev = pci_get_bus_and_slot(bus, dfn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
  	if (!dev)
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
  	switch (len) {
  	case 1:
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
35
  		cfg_ret = pci_user_read_config_byte(dev, off, &byte);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
  		break;
  	case 2:
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
38
  		cfg_ret = pci_user_read_config_word(dev, off, &word);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
  		break;
  	case 4:
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
41
  		cfg_ret = pci_user_read_config_dword(dev, off, &dword);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
  		break;
  	default:
  		err = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  		goto error;
f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
46
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  
  	err = -EIO;
  	if (cfg_ret != PCIBIOS_SUCCESSFUL)
  		goto error;
  
  	switch (len) {
  	case 1:
  		err = put_user(byte, (unsigned char __user *)buf);
  		break;
  	case 2:
  		err = put_user(word, (unsigned short __user *)buf);
  		break;
  	case 4:
  		err = put_user(dword, (unsigned int __user *)buf);
  		break;
e4585da22   Alan Cox   pci syscall.c: Sw...
62
63
  	}
  	pci_dev_put(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  	return err;
  
  error:
  	/* ??? XFree86 doesn't even check the return value.  They
  	   just look for 0xffffffff in the output, since that's what
  	   they get instead of a machine check on x86.  */
  	switch (len) {
  	case 1:
  		put_user(-1, (unsigned char __user *)buf);
  		break;
  	case 2:
  		put_user(-1, (unsigned short __user *)buf);
  		break;
  	case 4:
  		put_user(-1, (unsigned int __user *)buf);
  		break;
e4585da22   Alan Cox   pci syscall.c: Sw...
80
81
  	}
  	pci_dev_put(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
  	return err;
  }
c4ea37c26   Heiko Carstens   [CVE-2009-0029] S...
84
85
  SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn,
  		unsigned long, off, unsigned long, len, void __user *, buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
90
91
92
93
94
  {
  	struct pci_dev *dev;
  	u8 byte;
  	u16 word;
  	u32 dword;
  	int err = 0;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
e4585da22   Alan Cox   pci syscall.c: Sw...
95
  	dev = pci_get_bus_and_slot(bus, dfn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
  	if (!dev)
  		return -ENODEV;
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
98
  	switch (len) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
101
102
  	case 1:
  		err = get_user(byte, (u8 __user *)buf);
  		if (err)
  			break;
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
103
  		err = pci_user_write_config_byte(dev, off, byte);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
109
110
111
  		if (err != PCIBIOS_SUCCESSFUL)
  			err = -EIO;
  		break;
  
  	case 2:
  		err = get_user(word, (u16 __user *)buf);
  		if (err)
  			break;
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
112
  		err = pci_user_write_config_word(dev, off, word);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
116
117
118
119
120
  		if (err != PCIBIOS_SUCCESSFUL)
  			err = -EIO;
  		break;
  
  	case 4:
  		err = get_user(dword, (u32 __user *)buf);
  		if (err)
  			break;
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
121
  		err = pci_user_write_config_dword(dev, off, dword);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
127
128
  		if (err != PCIBIOS_SUCCESSFUL)
  			err = -EIO;
  		break;
  
  	default:
  		err = -EINVAL;
  		break;
e4585da22   Alan Cox   pci syscall.c: Sw...
129
  	}
e4585da22   Alan Cox   pci syscall.c: Sw...
130
  	pci_dev_put(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
  	return err;
  }