[PATCH v3 2/8] gdbstub: Try unlinking the unix socket before binding

Ilya Leoshkevich posted 8 patches 3 months, 3 weeks ago
There is a newer version of this series
[PATCH v3 2/8] gdbstub: Try unlinking the unix socket before binding
Posted by Ilya Leoshkevich 3 months, 3 weeks ago
In case an emulated process execve()s another emulated process, bind()
will fail, because the socket already exists. So try deleting it.

Note that it is not possible to handle this in do_execv(): deleting
gdbserver_user_state.socket_path before safe_execve() is not correct,
because the latter may fail, and afterwards we may lose control.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 gdbstub/user.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gdbstub/user.c b/gdbstub/user.c
index ef52f249ce9..c900d0a52fe 100644
--- a/gdbstub/user.c
+++ b/gdbstub/user.c
@@ -337,6 +337,7 @@ static int gdbserver_open_socket(const char *path)
 
     sockaddr.sun_family = AF_UNIX;
     pstrcpy(sockaddr.sun_path, sizeof(sockaddr.sun_path) - 1, path);
+    unlink(sockaddr.sun_path);
     ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
     if (ret < 0) {
         perror("bind socket");
-- 
2.47.0
Re: [PATCH v3 2/8] gdbstub: Try unlinking the unix socket before binding
Posted by Alex Bennée 3 months ago
Ilya Leoshkevich <iii@linux.ibm.com> writes:

> In case an emulated process execve()s another emulated process, bind()
> will fail, because the socket already exists. So try deleting it.
>
> Note that it is not possible to handle this in do_execv(): deleting
> gdbserver_user_state.socket_path before safe_execve() is not correct,
> because the latter may fail, and afterwards we may lose control.
>
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> ---
>  gdbstub/user.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/gdbstub/user.c b/gdbstub/user.c
> index ef52f249ce9..c900d0a52fe 100644
> --- a/gdbstub/user.c
> +++ b/gdbstub/user.c
> @@ -337,6 +337,7 @@ static int gdbserver_open_socket(const char *path)
>  
>      sockaddr.sun_family = AF_UNIX;
>      pstrcpy(sockaddr.sun_path, sizeof(sockaddr.sun_path) - 1, path);
> +    unlink(sockaddr.sun_path);

Should we be checking for errors here? What do we expect when attempting
to unlink a non-existent path? -EIO?

>      ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
>      if (ret < 0) {
>          perror("bind socket");

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro
Re: [PATCH v3 2/8] gdbstub: Try unlinking the unix socket before binding
Posted by Ilya Leoshkevich 3 months ago
On Wed, 2025-01-08 at 16:10 +0000, Alex Bennée wrote:
> Ilya Leoshkevich <iii@linux.ibm.com> writes:
> 
> > In case an emulated process execve()s another emulated process,
> > bind()
> > will fail, because the socket already exists. So try deleting it.
> > 
> > Note that it is not possible to handle this in do_execv(): deleting
> > gdbserver_user_state.socket_path before safe_execve() is not
> > correct,
> > because the latter may fail, and afterwards we may lose control.
> > 
> > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> > ---
> >  gdbstub/user.c | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/gdbstub/user.c b/gdbstub/user.c
> > index ef52f249ce9..c900d0a52fe 100644
> > --- a/gdbstub/user.c
> > +++ b/gdbstub/user.c
> > @@ -337,6 +337,7 @@ static int gdbserver_open_socket(const char
> > *path)
> >  
> >      sockaddr.sun_family = AF_UNIX;
> >      pstrcpy(sockaddr.sun_path, sizeof(sockaddr.sun_path) - 1,
> > path);
> > +    unlink(sockaddr.sun_path);
> 
> Should we be checking for errors here? What do we expect when
> attempting
> to unlink a non-existent path? -EIO?

ENOENT I guess.
I will add a check that requires either success or ENOENT.

> >      ret = bind(fd, (struct sockaddr *)&sockaddr,
> > sizeof(sockaddr));
> >      if (ret < 0) {
> >          perror("bind socket");