Re: [LTP] [PATCH v2] rpc: create valid fd to pass libtirpc validation

liujian (CE) via ltp
2026-01-17T08:16:35Z

> -----Original Message-----
> From: Petr Vorel [mailto:pvorel@suse.cz]
> Sent: Tuesday, January 13, 2026 8:26 PM
> To: liujian (CE) <liujian56@huawei.com>
> Cc: ltp@lists.linux.it; andrea.cervesato@suse.com; linux-nfs@vger.kernel.org;
> Steve Dickson <SteveD@redhat.com>
> Subject: Re: [LTP] [PATCH v2] rpc: create valid fd to pass libtirpc validation
>
> Hi all,
>
> [ Cc Steve and linux-nfs ]
>
> > The testcase(rpc_svc_destroy, rpc_svcfd_create, rpc_xprt_register,
> > rpc_xprt_unregister) was failing due to an invalid fd, which caused
> > libtirpc's internal validation to reject the operation.
> > This change ensures a valid socket fd is created and can pass the
> > validation checks in libtirpc.
>
> + I would also like to know more details about the failure (libtirpc
> + version, or
> do you still use Sun RPC from old glibc, distro, arch, ...).
>
tested this on Debian 12 and Debian 10.
I observed that the latest libtirpc (1.3.7) code has the same logic.

svcfd_create
----svc_fd_create(fd, sendsize, recvsize);
--------...
--------getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
--------...
--------getpeername(fd, (struct sockaddr *)(void *)&ss, &slen)
--------...

The above is some code flow of `svcfd_create()` in libtirpc, where both
`getsockname()` and `getpeername()` require the file descriptor (fd) to be
a valid and connected socket.
Additionally, in glibc, there are no similar operations in `svcfd_create()`,
so there is no issue for this test case.

> Because while we have some problems with some of these tests, I'm not
> sure if connecting to 127.0.0.1 is a valid approach. And if it is, should it be
> used in more tests? Also rpc_svc_destroy_stress.c and
> rpc_svcfd_create_limits.c use svcfd_create().
>
For a UDP socket, connect() does not trigger any message transmission and
should have no other side effects. What do you all think?
However, there are no `rpc_svcfd_create_limits` or `rpc_svc_destroy_stress`
tests in `runtest/net.rpc_tests`?

> Below are few minor implementation details. First, maybe add a common
> header, with code in the function which would be used? But it can be done
> later (RPC test code is really awful, more duplicity will not make it worse).
>
> > Signed-off-by: Liu Jian <liujian56@huawei.com>
> > ---
> > v2: Fix a compilation error on Alpine.
> > .../rpc_svc_destroy.c | 27 +++++++++++++++++++
> > .../rpc_svcfd_create.c | 26 ++++++++++++++++++
> > .../rpc_xprt_register.c | 25 +++++++++++++++++
> > .../rpc_xprt_unregister.c | 25 +++++++++++++++++
> > 4 files changed, 103 insertions(+)
>
> > diff --git
> > a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_created
> > estroy_svc_destroy/rpc_svc_destroy.c
> > b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_created
> > estroy_svc_destroy/rpc_svc_destroy.c
> > index 22e560843..b9240ccba 100644
> > ---
> > a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_created
> > estroy_svc_destroy/rpc_svc_destroy.c
> > +++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_cre
> > +++ atedestroy_svc_destroy/rpc_svc_destroy.c
> > @@ -30,6 +30,12 @@
> > #include <time.h>
> > #include <rpc/rpc.h>
>
> > +#include <unistd.h>
> > +#include <sys/socket.h>
> > +#include <netinet/in.h>
> > +#include <arpa/inet.h>
> > +#include <string.h>
> > +
> > //Standard define
> > #define PROCNUM 1
> > #define VERSNUM 1
> > @@ -43,6 +49,27 @@ int main(void)
> > int test_status = 1; //Default test result set to FAILED
> > int fd = 0;
> > SVCXPRT *svcr = NULL;
> > + struct sockaddr_in server_addr;
> > +
> > + fd = socket(AF_INET, SOCK_DGRAM, 0);
> > + if (fd < 0) {
> > + printf("socket creation failed");
> Maybe fprintf(stderr, ...) or perror()?
>
> > + return test_status;
> > + }
> > +
> > + memset(&server_addr, 0, sizeof(server_addr));
>
> Maybe just:
> struct sockaddr_in server_addr = {0};
> instead of memset() ?
>
> > + server_addr.sin_family = AF_INET;
> > + server_addr.sin_port = htons(9001);
> > + if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
> > + printf("inet_pton failed");
> > + close(fd);
> > + return test_status;
> > + }
> > + if (connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr))
> < 0) {
> > + printf("connect failed");
> > + close(fd);
> Funny that all testsuites don't close fd, but not closing single fd is not that
> problematic.
>
> Kind regards,
> Petr
>
> > + return test_status;
> > + }
>
> > //First of all, create a server
> > svcr = svcfd_create(fd, 0, 0);
> > diff --git
> > a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_created
> > estroy_svcfd_create/rpc_svcfd_create.c
> > b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_created
> > estroy_svcfd_create/rpc_svcfd_create.c
> > index f0d89ba48..ea4418961 100644
> > ---
> > a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_created
> > estroy_svcfd_create/rpc_svcfd_create.c
> > +++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_cre
> > +++ atedestroy_svcfd_create/rpc_svcfd_create.c
> > @@ -29,6 +29,11 @@
> > #include <stdlib.h>
> > #include <time.h>
> > #include <rpc/rpc.h>
> > +#include <unistd.h>
> > +#include <sys/socket.h>
> > +#include <netinet/in.h>
> > +#include <arpa/inet.h>
> > +#include <string.h>
>
> > //Standard define
> > #define PROCNUM 1
> > @@ -43,6 +48,27 @@ int main(void)
> > int test_status = 1; //Default test result set to FAILED
> > int fd = 0;
> > SVCXPRT *svcr = NULL;
> > + struct sockaddr_in server_addr;
> > +
> > + fd = socket(AF_INET, SOCK_DGRAM, 0);
> > + if (fd < 0) {
> > + printf("socket creation failed");
> > + return test_status;
> > + }
> > +
> > + memset(&server_addr, 0, sizeof(server_addr));
> > + server_addr.sin_family = AF_INET;
> > + server_addr.sin_port = htons(9001);
> > + if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
> > + printf("inet_pton failed");
> > + close(fd);
> > + return test_status;
> > + }
> > + if (connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr))
> < 0) {
> > + printf("connect failed");
> > + close(fd);
> > + return test_status;
> > + }
>
> > //create a server
> > svcr = svcfd_create(fd, 0, 0);
> > diff --git
> > a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunre
> > g_xprt_register/rpc_xprt_register.c
> > b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunre
> > g_xprt_register/rpc_xprt_register.c
> > index b10a1ce5e..a40dad7fe 100644
> > ---
> > a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunre
> > g_xprt_register/rpc_xprt_register.c
> > +++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_reg
> > +++ unreg_xprt_register/rpc_xprt_register.c
> > @@ -31,6 +31,10 @@
> > #include <rpc/rpc.h>
> > #include <sys/types.h>
> > #include <sys/socket.h>
> > +#include <unistd.h>
> > +#include <netinet/in.h>
> > +#include <arpa/inet.h>
> > +#include <string.h>
>
> > //Standard define
> > #define PROCNUM 1
> > @@ -45,6 +49,27 @@ int main(void)
> > int test_status = 1; //Default test result set to FAILED
> > SVCXPRT *svcr = NULL;
> > int fd = 0;
> > + struct sockaddr_in server_addr;
> > +
> > + fd = socket(AF_INET, SOCK_DGRAM, 0);
> > + if (fd < 0) {
> > + printf("socket creation failed");
> > + return test_status;
> > + }
> > +
> > + memset(&server_addr, 0, sizeof(server_addr));
> > + server_addr.sin_family = AF_INET;
> > + server_addr.sin_port = htons(9001);
> > + if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
> > + printf("inet_pton failed");
> > + close(fd);
> > + return test_status;
> > + }
> > + if (connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr))
> < 0) {
> > + printf("connect failed");
> > + close(fd);
> > + return test_status;
> > + }
>
> > //create a server
> > svcr = svcfd_create(fd, 1024, 1024); diff --git
> > a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunre
> > g_xprt_unregister/rpc_xprt_unregister.c
> > b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunre
> > g_xprt_unregister/rpc_xprt_unregister.c
> > index 3b6130eaa..5ac51de41 100644
> > ---
> > a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunre
> > g_xprt_unregister/rpc_xprt_unregister.c
> > +++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_reg
> > +++ unreg_xprt_unregister/rpc_xprt_unregister.c
> > @@ -31,6 +31,10 @@
> > #include <rpc/rpc.h>
> > #include <sys/types.h>
> > #include <sys/socket.h>
> > +#include <unistd.h>
> > +#include <netinet/in.h>
> > +#include <arpa/inet.h>
> > +#include <string.h>
>
> > //Standard define
> > #define PROCNUM 1
> > @@ -49,6 +53,27 @@ int main(int argn, char *argc[])
> > int test_status = 1; //Default test result set to FAILED
> > SVCXPRT *svcr = NULL;
> > int fd = 0;
> > + struct sockaddr_in server_addr;
> > +
> > + fd = socket(AF_INET, SOCK_DGRAM, 0);
> > + if (fd < 0) {
> > + printf("socket creation failed");
> > + return test_status;
> > + }
> > +
> > + memset(&server_addr, 0, sizeof(server_addr));
> > + server_addr.sin_family = AF_INET;
> > + server_addr.sin_port = htons(9001);
> > + if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
> > + printf("inet_pton failed");
> > + close(fd);
> > + return test_status;
> > + }
> > + if (connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr))
> < 0) {
> > + printf("connect failed");
> > + close(fd);
> > + return test_status;
> > + }
>
> > //create a server
> > svcr = svcfd_create(fd, 1024, 1024);