cleanup /dev/pci code some:
read permision only required for listing, read/write required for read/write to registers fix a possible memory leak clean up error handling a bit Reviewed by: silence
This commit is contained in:
parent
f51e58036e
commit
d08239c1f7
@ -176,9 +176,14 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
const char *name;
|
||||
int error;
|
||||
|
||||
if (!(flag & FWRITE))
|
||||
if (!(flag & FWRITE) && cmd != PCIOCGETCONF)
|
||||
return EPERM;
|
||||
|
||||
/* make sure register is in bounds and aligned */
|
||||
if (cmd == PCIOCREAD || cmd == PCIOCWRITE)
|
||||
if (io->pi_reg < 0 || io->pi_reg + io->pi_width > PCI_REGMAX ||
|
||||
io->pi_reg & (io->pi_width - 1))
|
||||
error = EINVAL;
|
||||
|
||||
switch(cmd) {
|
||||
case PCIOCGETCONF:
|
||||
@ -196,15 +201,6 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
num_patterns = 0;
|
||||
dinfo = NULL;
|
||||
|
||||
/*
|
||||
* Hopefully the user won't pass in a null pointer, but it
|
||||
* can't hurt to check.
|
||||
*/
|
||||
if (cio == NULL) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the user specified an offset into the device list,
|
||||
* but the list has changed since they last called this
|
||||
@ -272,33 +268,11 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
sizeof(struct pci_match_conf)) != cio->pat_buf_len){
|
||||
/* The user made a mistake, return an error*/
|
||||
cio->status = PCI_GETCONF_ERROR;
|
||||
printf("pci_ioctl: pat_buf_len %d != "
|
||||
"num_patterns (%d) * sizeof(struct "
|
||||
"pci_match_conf) (%d)\npci_ioctl: "
|
||||
"pat_buf_len should be = %d\n",
|
||||
cio->pat_buf_len, cio->num_patterns,
|
||||
(int)sizeof(struct pci_match_conf),
|
||||
(int)sizeof(struct pci_match_conf) *
|
||||
cio->num_patterns);
|
||||
printf("pci_ioctl: do your headers match your "
|
||||
"kernel?\n");
|
||||
cio->num_matches = 0;
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the user's buffer to make sure it's readable.
|
||||
*/
|
||||
if (!useracc((caddr_t)cio->patterns,
|
||||
cio->pat_buf_len, VM_PROT_READ)) {
|
||||
printf("pci_ioctl: pattern buffer %p, "
|
||||
"length %u isn't user accessible for"
|
||||
" READ\n", cio->patterns,
|
||||
cio->pat_buf_len);
|
||||
error = EACCES;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Allocate a buffer to hold the patterns.
|
||||
*/
|
||||
@ -306,8 +280,10 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
M_WAITOK);
|
||||
error = copyin(cio->patterns, pattern_buf,
|
||||
cio->pat_buf_len);
|
||||
if (error != 0)
|
||||
break;
|
||||
if (error != 0) {
|
||||
error = EINVAL;
|
||||
goto getconfexit;
|
||||
}
|
||||
num_patterns = cio->num_patterns;
|
||||
|
||||
} else if ((cio->num_patterns > 0)
|
||||
@ -317,24 +293,11 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
*/
|
||||
cio->status = PCI_GETCONF_ERROR;
|
||||
cio->num_matches = 0;
|
||||
printf("pci_ioctl: invalid GETCONF arguments\n");
|
||||
error = EINVAL;
|
||||
break;
|
||||
} else
|
||||
pattern_buf = NULL;
|
||||
|
||||
/*
|
||||
* Make sure we can write to the match buffer.
|
||||
*/
|
||||
if (!useracc((caddr_t)cio->matches,
|
||||
cio->match_buf_len, VM_PROT_WRITE)) {
|
||||
printf("pci_ioctl: match buffer %p, length %u "
|
||||
"isn't user accessible for WRITE\n",
|
||||
cio->matches, cio->match_buf_len);
|
||||
error = EACCES;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through the list of devices and copy out the devices
|
||||
* that match the user's criteria.
|
||||
@ -342,7 +305,7 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
for (cio->num_matches = 0, error = 0, i = 0,
|
||||
dinfo = STAILQ_FIRST(devlist_head);
|
||||
(dinfo != NULL) && (cio->num_matches < ionum)
|
||||
&& (error == 0) && (i < pci_numdevs);
|
||||
&& (error == 0) && (i < pci_numdevs) && (dinfo != NULL);
|
||||
dinfo = STAILQ_NEXT(dinfo, pci_links), i++) {
|
||||
|
||||
if (i < cio->offset)
|
||||
@ -375,10 +338,12 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
if (cio->num_matches >= ionum)
|
||||
break;
|
||||
|
||||
error = copyout(&dinfo->conf,
|
||||
&cio->matches[cio->num_matches],
|
||||
sizeof(struct pci_conf));
|
||||
cio->num_matches++;
|
||||
/* only if can copy it out do we count it */
|
||||
if (!(error = copyout(&dinfo->conf,
|
||||
&cio->matches[cio->num_matches],
|
||||
sizeof(struct pci_conf)))) {
|
||||
cio->num_matches++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,6 +370,7 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
else
|
||||
cio->status = PCI_GETCONF_MORE_DEVS;
|
||||
|
||||
getconfexit:
|
||||
if (pattern_buf != NULL)
|
||||
free(pattern_buf, M_TEMP);
|
||||
|
||||
@ -439,7 +405,7 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error = ENODEV;
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -473,7 +439,7 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error = ENODEV;
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user