<div dir="ltr">Sorry for the missing [PATCH lttng-tools]<div class="gmail_extra"><br><div class="gmail_quote">2017-05-11 15:36 GMT-04:00 Francis Deslauriers <span dir="ltr"><<a href="mailto:francis.deslauriers@efficios.com" target="_blank">francis.deslauriers@efficios.<wbr>com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The `pselect_fd_too_big` test is checking for the case where the `nfds`<br>
is larger than the number of open files allowed for this process<br>
(RLIMIT_NOFILE). According to the man page, if `nfds` > RLIMIT_NOFILE is<br>
evaluate to true the pselect6 syscall should return EINVAL.<br>
<br>
In fact, the Linux implementation of the pselect6 syscall[1] does not<br>
compare the `nfds` and RLIMIT_NOFILE but rather caps `nfds` to the<br>
highest numbered fd of the current process.<br>
<br>
It was observed elsewhere that there is a discrepancy between the manual<br>
page and the implementation [2].<br>
<br>
As a solution, replace the current testcase with one that checks the<br>
behaviour of the syscall when passed an invalid FD.<br>
<br>
[1]:<a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/select.c#n619" rel="noreferrer" target="_blank">https://git.kernel.org/pub<wbr>/scm/linux/kernel/git/torvalds<wbr>/linux.git/tree/fs/select.c#<wbr>n619</a><br>
[2]:<a href="https://patchwork.kernel.org/patch/9345805/" rel="noreferrer" target="_blank">https://patchwork.kernel.o<wbr>rg/patch/9345805/</a><br>
<br>
Signed-off-by: Francis Deslauriers <<a href="mailto:francis.deslauriers@efficios.com" target="_blank">francis.deslauriers@efficios.<wbr>com</a>><br>
Signed-off-by: Julien Desfossez <<a href="mailto:jdesfossez@efficios.com" target="_blank">jdesfossez@efficios.com</a>><br>
---<br>
 tests/regression/kernel/selec<wbr>t_poll_epoll.c        | 39 +++++++++++++---------<br>
 tests/regression/kernel/test_<wbr>select_poll_epoll     |  6 ++--<br>
 .../kernel/validate_select_po<wbr>ll_epoll.py           | 13 ++++----<br>
 3 files changed, 33 insertions(+), 25 deletions(-)<br>
<br>
diff --git a/tests/regression/kernel/sele<wbr>ct_poll_epoll.c b/tests/regression/kernel/sele<wbr>ct_poll_epoll.c<br>
index 4b703b3..1d767b0 100644<br>
--- a/tests/regression/kernel/sele<wbr>ct_poll_epoll.c<br>
+++ b/tests/regression/kernel/sele<wbr>ct_poll_epoll.c<br>
@@ -437,30 +437,38 @@ void ppoll_fds_ulong_max(void)<br>
 }<br>
<br>
 /*<br>
- * Select is limited to 1024 FDs, should output a pselect event<br>
- * with 0 FDs.<br>
+ * Pass a invalid file descriptor to pselect6(). The syscall should return<br>
+ * -EBADF. The recorded event should contain a ret=-EBADF (-9).<br>
  */<br>
-void pselect_fd_too_big(void)<br>
+void pselect_invalid_fd(void)<br>
 {<br>
-       long rfds[2048 / (sizeof(long) * CHAR_BIT)] = { 0 };<br>
+       fd_set rfds;<br>
        int ret;<br>
-       int fd2;<br>
+       int fd;<br>
        char buf[BUF_SIZE];<br>
<br>
        /*<br>
-        * Test if nfds > 1024.<br>
-        * Make sure ulimit is set correctly (ulimit -n 2048).<br>
+        * Open a file, close it and use the closed FD in the pselect6 call<br>
         */<br>
-       fd2 = dup2(wait_fd, 2047);<br>
-       if (fd2 != 2047) {<br>
-               perror("dup2");<br>
-               return;<br>
+<br>
+       fd = open("/dev/null", O_RDONLY);<br>
+       if (fd == -1) {<br>
+               perror("open");<br>
+               goto error;<br>
        }<br>
<br>
-       FD_SET(fd2, (fd_set *) &rfds);<br>
-       ret = syscall(SYS_pselect6, fd2 + 1, &rfds, NULL, NULL, NULL, NULL);<br>
+       ret = close(fd);<br>
<br>
        if (ret == -1) {<br>
+               perror("close");<br>
+               goto error;<br>
+       }<br>
+<br>
+       FD_ZERO(&rfds);<br>
+       FD_SET(fd, &rfds);<br>
+<br>
+       ret = syscall(SYS_pselect6, fd + 1, &rfds, NULL, NULL, NULL, NULL);<br>
+       if (ret == -1) {<br>
                perror("# pselect()");<br>
        } else if (ret) {<br>
                printf("# [pselect] data available\n");<br>
@@ -471,7 +479,8 @@ void pselect_fd_too_big(void)<br>
        } else {<br>
                printf("# [pselect] timeout\n");<br>
        }<br>
-<br>
+error:<br>
+       return;<br>
 }<br>
<br>
 /*<br>
@@ -892,7 +901,7 @@ int main(int argc, const char **argv)<br>
                run_working_cases();<br>
                break;<br>
        case 3:<br>
-               pselect_fd_too_big();<br>
+               pselect_invalid_fd();<br>
                break;<br>
        case 4:<br>
                test_ppoll_big();<br>
diff --git a/tests/regression/kernel/test<wbr>_select_poll_epoll b/tests/regression/kernel/test<wbr>_select_poll_epoll<br>
index e01866f..ec034e6 100755<br>
--- a/tests/regression/kernel/test<wbr>_select_poll_epoll<br>
+++ b/tests/regression/kernel/test<wbr>_select_poll_epoll<br>
@@ -126,13 +126,13 @@ function test_timeout_cases()<br>
        rm -rf $TRACE_PATH<br>
 }<br>
<br>
-function test_big_pselect()<br>
+function test_pselect_invalid_fd()<br>
 {<br>
        TRACE_PATH=$(mktemp -d)<br>
        SESSION_NAME="syscall_payload"<br>
        SYSCALL_LIST="pselect6"<br>
<br>
-       diag "pselect with a FD > 1023"<br>
+       diag "pselect with invalid FD"<br>
<br>
        create_lttng_session_ok $SESSION_NAME $TRACE_PATH<br>
<br>
@@ -384,7 +384,7 @@ skip $isroot "Root access is needed. Skipping all tests." $NUM_TESTS ||<br>
<br>
        test_working_cases<br>
        test_timeout_cases<br>
-       test_big_pselect<br>
+       test_pselect_invalid_fd<br>
        test_big_ppoll<br>
        test_ppoll_overflow<br>
        test_pselect_invalid_ptr<br>
diff --git a/tests/regression/kernel/vali<wbr>date_select_poll_epoll.py b/tests/regression/kernel/vali<wbr>date_select_poll_epoll.py<br>
index f4946e7..613cec3 100755<br>
--- a/tests/regression/kernel/vali<wbr>date_select_poll_epoll.py<br>
+++ b/tests/regression/kernel/vali<wbr>date_select_poll_epoll.py<br>
@@ -450,8 +450,8 @@ class Test2(TraceParser):<br>
 class Test3(TraceParser):<br>
     def __init__(self, trace, pid):<br>
         super().__init__(trace, pid)<br>
-        self.expect["select_too_big_in<wbr>"] = 0<br>
-        self.expect["select_too_big_ou<wbr>t"] = 0<br>
+        self.expect["select_invalid_fd<wbr>_in"] = 0<br>
+        self.expect["select_invalid_fd<wbr>_out"] = 0<br>
<br>
     def select_entry(self, event):<br>
         timestamp = event.timestamp<br>
@@ -466,9 +466,8 @@ class Test3(TraceParser):<br>
         _exceptfds_length = event["_exceptfds_length"]<br>
         exceptfds = event["exceptfds"]<br>
<br>
-        # make sure an invalid value still produces a valid event<br>
-        if n == 2048 and overflow == 0 and _readfds_length == 0:<br>
-            self.expect["select_too_big_in<wbr>"] = 1<br>
+        if n > 0 and overflow == 0:<br>
+            self.expect["select_invalid_fd<wbr>_in"] = 1<br>
<br>
     def select_exit(self, event):<br>
         timestamp = event.timestamp<br>
@@ -483,9 +482,9 @@ class Test3(TraceParser):<br>
         _exceptfds_length = event["_exceptfds_length"]<br>
         exceptfds = event["exceptfds"]<br>
<br>
-        # make sure an invalid value still produces a valid event<br>
+        # make sure the event has a ret field equal to -EBADF<br>
         if ret == -9 and overflow == 0 and _readfds_length == 0:<br>
-            self.expect["select_too_big_ou<wbr>t"] = 1<br>
+            self.expect["select_invalid_fd<wbr>_out"] = 1<br>
<br>
<br>
 class Test4(TraceParser):<br>
<span class="m_6919143413702466878HOEnZb"><font color="#888888">--<br>
2.7.4<br>
<br>
</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="m_6919143413702466878gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div>Francis Deslauriers</div><div dir="ltr">Software developer<div>EfficiOS inc.</div></div></div></div></div>
</div></div>