Page MenuHomeFreeBSD

D30690.diff
No OneTemporary

D30690.diff

diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -1417,12 +1417,13 @@
return (kern_poll(td, uap->fds, uap->nfds, tsp, NULL));
}
+/*
+ * kfds points to an array in the kernel.
+ */
int
-kern_poll(struct thread *td, struct pollfd *ufds, u_int nfds,
+kern_poll_kfds(struct thread *td, struct pollfd *kfds, u_int nfds,
struct timespec *tsp, sigset_t *uset)
{
- struct pollfd *kfds;
- struct pollfd stackfds[32];
sbintime_t sbt, precision, tmp;
time_t over;
struct timespec ts;
@@ -1453,28 +1454,11 @@
} else
sbt = -1;
- /*
- * This is kinda bogus. We have fd limits, but that is not
- * really related to the size of the pollfd array. Make sure
- * we let the process use at least FD_SETSIZE entries and at
- * least enough for the system-wide limits. We want to be reasonably
- * safe, but not overly restrictive.
- */
- if (nfds > maxfilesperproc && nfds > FD_SETSIZE)
- return (EINVAL);
- if (nfds > nitems(stackfds))
- kfds = mallocarray(nfds, sizeof(*kfds), M_TEMP, M_WAITOK);
- else
- kfds = stackfds;
- error = copyin(ufds, kfds, nfds * sizeof(*kfds));
- if (error)
- goto done;
-
if (uset != NULL) {
error = kern_sigprocmask(td, SIG_SETMASK, uset,
&td->td_oldsigmask, 0);
if (error)
- goto done;
+ return (error);
td->td_pflags |= TDP_OLDMASK;
/*
* Make sure that ast() is called on return to
@@ -1501,20 +1485,11 @@
}
seltdclear(td);
-done:
/* poll is not restarted after signals... */
if (error == ERESTART)
error = EINTR;
if (error == EWOULDBLOCK)
error = 0;
- if (error == 0) {
- error = pollout(td, kfds, ufds, nfds);
- if (error)
- goto out;
- }
-out:
- if (nfds > nitems(stackfds))
- free(kfds, M_TEMP);
return (error);
}
@@ -1539,12 +1514,52 @@
ssp = &set;
} else
ssp = NULL;
+ return (kern_poll(td, uap->fds, uap->nfds, tsp, ssp));
+}
+
+/*
+ * ufds points to an array in user space.
+ */
+int
+kern_poll(struct thread *td, struct pollfd *ufds, u_int nfds,
+ struct timespec *tsp, sigset_t *set)
+{
+ struct pollfd *kfds;
+ struct pollfd stackfds[32];
+ int error;
+
+ if (kern_poll_maxfds(nfds))
+ return (EINVAL);
+ if (nfds > nitems(stackfds))
+ kfds = mallocarray(nfds, sizeof(*kfds), M_TEMP, M_WAITOK);
+ else
+ kfds = stackfds;
+ error = copyin(ufds, kfds, nfds * sizeof(*kfds));
+ if (error != 0)
+ goto out;
+
+ error = kern_poll_kfds(td, kfds, nfds, tsp, set);
+ if (error == 0)
+ error = pollout(td, kfds, ufds, nfds);
+
+out:
+ if (nfds > nitems(stackfds))
+ free(kfds, M_TEMP);
+ return (error);
+}
+
+bool
+kern_poll_maxfds(u_int nfds)
+{
+
/*
- * fds is still a pointer to user space. kern_poll() will
- * take care of copyin that array to the kernel space.
+ * This is kinda bogus. We have fd limits, but that is not
+ * really related to the size of the pollfd array. Make sure
+ * we let the process use at least FD_SETSIZE entries and at
+ * least enough for the system-wide limits. We want to be reasonably
+ * safe, but not overly restrictive.
*/
-
- return (kern_poll(td, uap->fds, uap->nfds, tsp, ssp));
+ return (nfds > maxfilesperproc && nfds > FD_SETSIZE);
}
static int
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -225,6 +225,9 @@
struct filecaps *fcaps1, struct filecaps *fcaps2);
int kern_poll(struct thread *td, struct pollfd *fds, u_int nfds,
struct timespec *tsp, sigset_t *uset);
+int kern_poll_kfds(struct thread *td, struct pollfd *fds, u_int nfds,
+ struct timespec *tsp, sigset_t *uset);
+bool kern_poll_maxfds(u_int nfds);
int kern_posix_error(struct thread *td, int error);
int kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len,
int advice);

File Metadata

Mime Type
text/plain
Expires
Thu, Feb 6, 8:36 PM (21 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16501125
Default Alt Text
D30690.diff (3 KB)

Event Timeline