public inbox for newlib@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Fix getlogin() to check only stdin to get a valid tty
@ 2023-07-12 17:33 Jordi Sanfeliu
  2023-07-12 18:50 ` Torbjorn SVENSSON
  2023-07-17 19:06 ` Jeff Johnston
  0 siblings, 2 replies; 15+ messages in thread
From: Jordi Sanfeliu @ 2023-07-12 17:33 UTC (permalink / raw)
  To: newlib

Hello,

In my hobby OS [1] which uses Newlib C as its libc, I noticed that the 
GNU command 'logname' does output nothing when it is redirected or pipe'd.

The current getlogin() implementation [2] forces the three primary file 
descriptors (stdin, stdout and stderr) to be a valid tty before checking 
the utmp file, otherwise it returns NULL. This makes impossible to 
redirect (to a file or to a pipe), the output of a program that is using 
this function because one of its file descriptors won't be a tty.

See:

# cat test.c
#include <stdio.h>

int main(void)
{
	char *user;

	if(user = getlogin()) {
		printf("%s\n", user);
	}

	return 0;
}

# ./test
root
# ./test > xx
# cat xx
# ./test | cat
#

To fix this, I thought that only checking if stdin is a valid tty would 
be enough.

Does this sound reasonable to you?
Thanks.



diff --git a/newlib/libc/unix/getlogin.c b/newlib/libc/unix/getlogin.c
index da4f47a95..e646bcb08 100644
--- a/newlib/libc/unix/getlogin.c
+++ b/newlib/libc/unix/getlogin.c
@@ -16,9 +16,7 @@ getlogin ()
    extern char *ttyname ();
    char *tty;

-  if (((tty = ttyname (0)) == 0)
-      || ((tty = ttyname (1)) == 0)
-      || ((tty = ttyname (2)) == 0))
+  if ((tty = ttyname (0)) == 0)
      return 0;

    if ((utmp_fd = open (UTMP_FILE, O_RDONLY)) == -1)


1. https://www.fiwix.org
2. 
https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/unix/getlogin.c;hb=HEAD

-- 
Jordi Sanfeliu
FIBRANET Network Services Provider
https://www.fibranet.cat

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-12 17:33 [PATCH] Fix getlogin() to check only stdin to get a valid tty Jordi Sanfeliu
@ 2023-07-12 18:50 ` Torbjorn SVENSSON
  2023-07-12 20:06   ` Brian Inglis
  2023-07-13  8:06   ` Jordi Sanfeliu
  2023-07-17 19:06 ` Jeff Johnston
  1 sibling, 2 replies; 15+ messages in thread
From: Torbjorn SVENSSON @ 2023-07-12 18:50 UTC (permalink / raw)
  To: newlib



On 2023-07-12 19:33, Jordi Sanfeliu via Newlib wrote:
> Hello,
> 
> In my hobby OS [1] which uses Newlib C as its libc, I noticed that the 
> GNU command 'logname' does output nothing when it is redirected or pipe'd.
> 
> The current getlogin() implementation [2] forces the three primary file 
> descriptors (stdin, stdout and stderr) to be a valid tty before checking 
> the utmp file, otherwise it returns NULL. This makes impossible to 
> redirect (to a file or to a pipe), the output of a program that is using 
> this function because one of its file descriptors won't be a tty.

I think your analysis is wrong. See below for reasons why.

> diff --git a/newlib/libc/unix/getlogin.c b/newlib/libc/unix/getlogin.c
> index da4f47a95..e646bcb08 100644
> --- a/newlib/libc/unix/getlogin.c
> +++ b/newlib/libc/unix/getlogin.c
> @@ -16,9 +16,7 @@ getlogin ()
>     extern char *ttyname ();
>     char *tty;
> 
> -  if (((tty = ttyname (0)) == 0)
> -      || ((tty = ttyname (1)) == 0)
> -      || ((tty = ttyname (2)) == 0))

These 3 lines of code checks if one of stdin, stdout or stderr is 
connected to a terminal device. If the return value of ttyname is 0, it 
means that there is no terminal device connected to that fd.
As I read the code, it first tries with stdin. If stdin is closed or 
redirected, it tries with stdout instead and then lastly, falls back to 
trying with stderr. If none of the 3 fd's provides a terminal device, 
then the getlogin will return 0.

As a result, doing your change would force the process to have a 
connected stdin or the getlogin call would return 0.

> +  if ((tty = ttyname (0)) == 0)
>       return 0;
> 
>     if ((utmp_fd = open (UTMP_FILE, O_RDONLY)) == -1)
> 
> 
> 1. https://www.fiwix.org
> 2. 
> https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/unix/getlogin.c;hb=HEAD
> 


While looking at the code pointed to in link 2, I'm a bit puzzled about 
the following lines:

static char buf[10];
...
strncpy (buf, utmp_buf.ut_user, sizeof (utmp_buf.ut_user));

As buf is 10 bytes, I suppose sizeof(utmp_buf.ut_user) should never be 
allowed to exceed 10 bytes, but in the newlib source tree, I find these 
files that define a size for utmp_buf.ut_user:

./newlib/libc/sys/sysvi386/sys/utmp.h: 8
./winsup/cygwin/include/cygwin/utmp.h: 16

I'm not sure if this getlogin.c file is included in a cygwin build, but 
if it is, I think there is a buffer overflow here.


Kind regards,
Torbjörn

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-12 18:50 ` Torbjorn SVENSSON
@ 2023-07-12 20:06   ` Brian Inglis
  2023-07-13 16:26     ` Torbjorn SVENSSON
  2023-07-13  8:06   ` Jordi Sanfeliu
  1 sibling, 1 reply; 15+ messages in thread
From: Brian Inglis @ 2023-07-12 20:06 UTC (permalink / raw)
  To: newlib

On 2023-07-12 12:50, Torbjorn SVENSSON wrote:
> 
> 
> On 2023-07-12 19:33, Jordi Sanfeliu via Newlib wrote:
>> Hello,
>>
>> In my hobby OS [1] which uses Newlib C as its libc, I noticed that the GNU 
>> command 'logname' does output nothing when it is redirected or pipe'd.
>>
>> The current getlogin() implementation [2] forces the three primary file 
>> descriptors (stdin, stdout and stderr) to be a valid tty before checking the 
>> utmp file, otherwise it returns NULL. This makes impossible to redirect (to a 
>> file or to a pipe), the output of a program that is using this function 
>> because one of its file descriptors won't be a tty.
> 
> I think your analysis is wrong. See below for reasons why.
> 
>> diff --git a/newlib/libc/unix/getlogin.c b/newlib/libc/unix/getlogin.c
>> index da4f47a95..e646bcb08 100644
>> --- a/newlib/libc/unix/getlogin.c
>> +++ b/newlib/libc/unix/getlogin.c
>> @@ -16,9 +16,7 @@ getlogin ()
>>     extern char *ttyname ();
>>     char *tty;
>>
>> -  if (((tty = ttyname (0)) == 0)
>> -      || ((tty = ttyname (1)) == 0)
>> -      || ((tty = ttyname (2)) == 0))
> 
> These 3 lines of code checks if one of stdin, stdout or stderr is connected to a 
> terminal device. If the return value of ttyname is 0, it means that there is no 
> terminal device connected to that fd.
> As I read the code, it first tries with stdin. If stdin is closed or redirected, 
> it tries with stdout instead and then lastly, falls back to trying with stderr. 
> If none of the 3 fd's provides a terminal device, then the getlogin will return 0.
> 
> As a result, doing your change would force the process to have a connected stdin 
> or the getlogin call would return 0.
> 
>> +  if ((tty = ttyname (0)) == 0)
>>       return 0;
>>
>>     if ((utmp_fd = open (UTMP_FILE, O_RDONLY)) == -1)
>>
>>
>> 1. https://www.fiwix.org
>> 2. 
>> https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/unix/getlogin.c;hb=HEAD
>>
> 
> 
> While looking at the code pointed to in link 2, I'm a bit puzzled about the 
> following lines:
> 
> static char buf[10];
> ...
> strncpy (buf, utmp_buf.ut_user, sizeof (utmp_buf.ut_user));
> 
> As buf is 10 bytes, I suppose sizeof(utmp_buf.ut_user) should never be allowed 
> to exceed 10 bytes, but in the newlib source tree, I find these files that 
> define a size for utmp_buf.ut_user:
> 
> ./newlib/libc/sys/sysvi386/sys/utmp.h: 8
> ./winsup/cygwin/include/cygwin/utmp.h: 16
> 
> I'm not sure if this getlogin.c file is included in a cygwin build, but if it 
> is, I think there is a buffer overflow here.

No worries: Cygwin getlogin/_r is defined as "C" in winsup/cygwin/uinfo.cc to 
deal with Windows and limits itself to UNLEN:
/usr/include/cygwin/limits.h:#define __LOGIN_NAME_MAX 256       /* equal to 
UNLEN defined in w32api/lmcons.h */
/usr/include/w32api/lmcons.h:#define UNLEN 256

-- 
Take care. Thanks, Brian Inglis              Calgary, Alberta, Canada

La perfection est atteinte                   Perfection is achieved
non pas lorsqu'il n'y a plus rien à ajouter  not when there is no more to add
mais lorsqu'il n'y a plus rien à retirer     but when there is no more to cut
                                 -- Antoine de Saint-Exupéry


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-12 18:50 ` Torbjorn SVENSSON
  2023-07-12 20:06   ` Brian Inglis
@ 2023-07-13  8:06   ` Jordi Sanfeliu
  2023-07-13 16:25     ` Torbjorn SVENSSON
  1 sibling, 1 reply; 15+ messages in thread
From: Jordi Sanfeliu @ 2023-07-13  8:06 UTC (permalink / raw)
  To: newlib

Hello Torbjörn,

Thanks for you reply.

It seems to me that this code returns 0 as soon as one of the 3 fds is 
0, regardless if the rest are valid tty names.

I think that what you meant is this:

         if ((tty = ttyname (0)) == 0)
             if ((tty = ttyname (1)) == 0)
                 if ((tty = ttyname (2)) == 0)
                     return 0;

which IMO would be even a better patch.

What do you think?

Best regards.


On 7/12/23 20:50, Torbjorn SVENSSON wrote:

>> -  if (((tty = ttyname (0)) == 0)
>> -      || ((tty = ttyname (1)) == 0)
>> -      || ((tty = ttyname (2)) == 0))
> 
> These 3 lines of code checks if one of stdin, stdout or stderr is 
> connected to a terminal device. If the return value of ttyname is 0, it 
> means that there is no terminal device connected to that fd.
> As I read the code, it first tries with stdin. If stdin is closed or 
> redirected, it tries with stdout instead and then lastly, falls back to 
> trying with stderr. If none of the 3 fd's provides a terminal device, 
> then the getlogin will return 0.

-- 
Jordi Sanfeliu
FIBRANET Network Services Provider
https://www.fibranet.cat

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-13  8:06   ` Jordi Sanfeliu
@ 2023-07-13 16:25     ` Torbjorn SVENSSON
  2023-07-13 16:57       ` Jordi Sanfeliu
  0 siblings, 1 reply; 15+ messages in thread
From: Torbjorn SVENSSON @ 2023-07-13 16:25 UTC (permalink / raw)
  To: newlib



On 2023-07-13 10:06, Jordi Sanfeliu via Newlib wrote:
> Hello Torbjörn,
> 
> Thanks for you reply.
> 
> It seems to me that this code returns 0 as soon as one of the 3 fds is 
> 0, regardless if the rest are valid tty names.
> 
> I think that what you meant is this:
> 
>          if ((tty = ttyname (0)) == 0)
>              if ((tty = ttyname (1)) == 0)
>                  if ((tty = ttyname (2)) == 0)
>                      return 0;
> 
> which IMO would be even a better patch.
> 
> What do you think?

Actually, you're right. Sorry for the confusion.
I took a sneak peak at how glibc does this and there is this comment:

   /* Get name of tty connected to fd 0.  Return NULL if not a tty or
      if fd 0 isn't open.  Note that a lot of documentation says that
      getlogin() is based on the controlling terminal---what they
      really mean is "the terminal connected to standard input".  The
      getlogin() implementation of DEC Unix, SunOS, Solaris, HP-UX all
      return NULL if fd 0 has been closed, so this is the compatible
      thing to do.  Note that ttyname(open("/dev/tty")) on those
      systems returns /dev/tty, so that is not a possible solution for
      getlogin().  */

Based on this comment, I guess it would be sane to drop the check on 
stdout and stderr, but it would have the consequence that you are not 
able to pipe some data on stdin to the application that calls getlogin 
as it would fail in that scenario.

I'm not a maintainer of newlib so I don't really have anything to say 
about what path you decide to go.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-12 20:06   ` Brian Inglis
@ 2023-07-13 16:26     ` Torbjorn SVENSSON
  0 siblings, 0 replies; 15+ messages in thread
From: Torbjorn SVENSSON @ 2023-07-13 16:26 UTC (permalink / raw)
  To: newlib



On 2023-07-12 22:06, Brian Inglis wrote:
> No worries: Cygwin getlogin/_r is defined as "C" in 
> winsup/cygwin/uinfo.cc to deal with Windows and limits itself to UNLEN:
> /usr/include/cygwin/limits.h:#define __LOGIN_NAME_MAX 256       /* equal 
> to UNLEN defined in w32api/lmcons.h */
> /usr/include/w32api/lmcons.h:#define UNLEN 256
> 

Thanks Brian for the clarification!

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-13 16:25     ` Torbjorn SVENSSON
@ 2023-07-13 16:57       ` Jordi Sanfeliu
  2023-07-13 19:01         ` Jeff Johnston
  2023-07-13 21:12         ` Stefan Tauner
  0 siblings, 2 replies; 15+ messages in thread
From: Jordi Sanfeliu @ 2023-07-13 16:57 UTC (permalink / raw)
  To: newlib

Hello,

So we have two possible patches to solve this situation:

My first original patch that only checks if stdin is a tty and seems to 
match with glibc comments provided by Torbjörn. The only problem is that 
it won't work in the scenario when someone pipes some data on stdin to 
the application:

$ echo | ./test
$


diff --git a/newlib/libc/unix/getlogin.c b/newlib/libc/unix/getlogin.c
index da4f47a95..e646bcb08 100644
--- a/newlib/libc/unix/getlogin.c
+++ b/newlib/libc/unix/getlogin.c
@@ -16,9 +16,7 @@ getlogin ()
    extern char *ttyname ();
    char *tty;

-  if (((tty = ttyname (0)) == 0)
-      || ((tty = ttyname (1)) == 0)
-      || ((tty = ttyname (2)) == 0))
+  if ((tty = ttyname (0)) == 0)
      return 0;

    if ((utmp_fd = open (UTMP_FILE, O_RDONLY)) == -1)



And a patch based on the comments of Torbjörn that checks all three fds 
before returning NULL:

diff --git a/newlib/libc/unix/getlogin.c b/newlib/libc/unix/getlogin.c
index da4f47a95..5a3f172e7 100644
--- a/newlib/libc/unix/getlogin.c
+++ b/newlib/libc/unix/getlogin.c
@@ -16,10 +16,10 @@ getlogin ()
    extern char *ttyname ();
    char *tty;

-  if (((tty = ttyname (0)) == 0)
-      || ((tty = ttyname (1)) == 0)
-      || ((tty = ttyname (2)) == 0))
-    return 0;
+  if ((tty = ttyname (0)) == 0)
+      if ((tty = ttyname (1)) == 0)
+          if ((tty = ttyname (2)) == 0)
+              return 0;

    if ((utmp_fd = open (UTMP_FILE, O_RDONLY)) == -1)
      return 0;


Any thoughts?
Thanks.


On 7/13/23 18:25, Torbjorn SVENSSON wrote:

> I took a sneak peak at how glibc does this and there is this comment:
> 
>    /* Get name of tty connected to fd 0.  Return NULL if not a tty or
>       if fd 0 isn't open.  Note that a lot of documentation says that
>       getlogin() is based on the controlling terminal---what they
>       really mean is "the terminal connected to standard input".  The
>       getlogin() implementation of DEC Unix, SunOS, Solaris, HP-UX all
>       return NULL if fd 0 has been closed, so this is the compatible
>       thing to do.  Note that ttyname(open("/dev/tty")) on those
>       systems returns /dev/tty, so that is not a possible solution for
>       getlogin().  */
> 
> Based on this comment, I guess it would be sane to drop the check on 
> stdout and stderr, but it would have the consequence that you are not 
> able to pipe some data on stdin to the application that calls getlogin 
> as it would fail in that scenario.
> 
> I'm not a maintainer of newlib so I don't really have anything to say 
> about what path you decide to go.

-- 
Jordi Sanfeliu
FIBRANET Network Services Provider
https://www.fibranet.cat

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-13 16:57       ` Jordi Sanfeliu
@ 2023-07-13 19:01         ` Jeff Johnston
  2023-07-17  7:54           ` Corinna Vinschen
  2023-07-13 21:12         ` Stefan Tauner
  1 sibling, 1 reply; 15+ messages in thread
From: Jeff Johnston @ 2023-07-13 19:01 UTC (permalink / raw)
  To: Jordi Sanfeliu, newlib

[-- Attachment #1: Type: text/plain, Size: 3165 bytes --]

I think that when in doubt, going with glibc is the right answer.

I'll give Corinna time to pipe in if she wishes, otherwise, I'll check in
the glibc-like patch.

-- Jeff J.

On Thu, Jul 13, 2023 at 12:58 PM Jordi Sanfeliu via Newlib <
newlib@sourceware.org> wrote:

> Hello,
>
> So we have two possible patches to solve this situation:
>
> My first original patch that only checks if stdin is a tty and seems to
> match with glibc comments provided by Torbjörn. The only problem is that
> it won't work in the scenario when someone pipes some data on stdin to
> the application:
>
> $ echo | ./test
> $
>
>
> diff --git a/newlib/libc/unix/getlogin.c b/newlib/libc/unix/getlogin.c
> index da4f47a95..e646bcb08 100644
> --- a/newlib/libc/unix/getlogin.c
> +++ b/newlib/libc/unix/getlogin.c
> @@ -16,9 +16,7 @@ getlogin ()
>     extern char *ttyname ();
>     char *tty;
>
> -  if (((tty = ttyname (0)) == 0)
> -      || ((tty = ttyname (1)) == 0)
> -      || ((tty = ttyname (2)) == 0))
> +  if ((tty = ttyname (0)) == 0)
>       return 0;
>
>     if ((utmp_fd = open (UTMP_FILE, O_RDONLY)) == -1)
>
>
>
> And a patch based on the comments of Torbjörn that checks all three fds
> before returning NULL:
>
> diff --git a/newlib/libc/unix/getlogin.c b/newlib/libc/unix/getlogin.c
> index da4f47a95..5a3f172e7 100644
> --- a/newlib/libc/unix/getlogin.c
> +++ b/newlib/libc/unix/getlogin.c
> @@ -16,10 +16,10 @@ getlogin ()
>     extern char *ttyname ();
>     char *tty;
>
> -  if (((tty = ttyname (0)) == 0)
> -      || ((tty = ttyname (1)) == 0)
> -      || ((tty = ttyname (2)) == 0))
> -    return 0;
> +  if ((tty = ttyname (0)) == 0)
> +      if ((tty = ttyname (1)) == 0)
> +          if ((tty = ttyname (2)) == 0)
> +              return 0;
>
>     if ((utmp_fd = open (UTMP_FILE, O_RDONLY)) == -1)
>       return 0;
>
>
> Any thoughts?
> Thanks.
>
>
> On 7/13/23 18:25, Torbjorn SVENSSON wrote:
>
> > I took a sneak peak at how glibc does this and there is this comment:
> >
> >    /* Get name of tty connected to fd 0.  Return NULL if not a tty or
> >       if fd 0 isn't open.  Note that a lot of documentation says that
> >       getlogin() is based on the controlling terminal---what they
> >       really mean is "the terminal connected to standard input".  The
> >       getlogin() implementation of DEC Unix, SunOS, Solaris, HP-UX all
> >       return NULL if fd 0 has been closed, so this is the compatible
> >       thing to do.  Note that ttyname(open("/dev/tty")) on those
> >       systems returns /dev/tty, so that is not a possible solution for
> >       getlogin().  */
> >
> > Based on this comment, I guess it would be sane to drop the check on
> > stdout and stderr, but it would have the consequence that you are not
> > able to pipe some data on stdin to the application that calls getlogin
> > as it would fail in that scenario.
> >
> > I'm not a maintainer of newlib so I don't really have anything to say
> > about what path you decide to go.
>
> --
> Jordi Sanfeliu
> FIBRANET Network Services Provider
> https://www.fibranet.cat
>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-13 16:57       ` Jordi Sanfeliu
  2023-07-13 19:01         ` Jeff Johnston
@ 2023-07-13 21:12         ` Stefan Tauner
  1 sibling, 0 replies; 15+ messages in thread
From: Stefan Tauner @ 2023-07-13 21:12 UTC (permalink / raw)
  To: newlib; +Cc: Jordi Sanfeliu

On Thu, 13 Jul 2023 18:57:32 +0200
Jordi Sanfeliu via Newlib <newlib@sourceware.org> wrote:

> -  if (((tty = ttyname (0)) == 0)
> -      || ((tty = ttyname (1)) == 0)
> -      || ((tty = ttyname (2)) == 0))
> -    return 0;
> +  if ((tty = ttyname (0)) == 0)
> +      if ((tty = ttyname (1)) == 0)
> +          if ((tty = ttyname (2)) == 0)
> +              return 0;

IMHO the bug arose simply because of a || vs. && confusion. You can
just replace the || with && and have exactly the same effect as this
patch but it would be more customary.
-- 
Kind regards/Mit freundlichen Grüßen, Stefan Tauner

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-13 19:01         ` Jeff Johnston
@ 2023-07-17  7:54           ` Corinna Vinschen
  0 siblings, 0 replies; 15+ messages in thread
From: Corinna Vinschen @ 2023-07-17  7:54 UTC (permalink / raw)
  To: newlib

On Jul 13 15:01, Jeff Johnston wrote:
> I think that when in doubt, going with glibc is the right answer.
> 
> I'll give Corinna time to pipe in if she wishes, otherwise, I'll check in
> the glibc-like patch.

Sounds right to me.


Corinna

> 
> -- Jeff J.
> 
> On Thu, Jul 13, 2023 at 12:58 PM Jordi Sanfeliu via Newlib <
> newlib@sourceware.org> wrote:
> 
> > Hello,
> >
> > So we have two possible patches to solve this situation:
> >
> > My first original patch that only checks if stdin is a tty and seems to
> > match with glibc comments provided by Torbjörn. The only problem is that
> > it won't work in the scenario when someone pipes some data on stdin to
> > the application:
> >
> > $ echo | ./test
> > $
> >
> >
> > diff --git a/newlib/libc/unix/getlogin.c b/newlib/libc/unix/getlogin.c
> > index da4f47a95..e646bcb08 100644
> > --- a/newlib/libc/unix/getlogin.c
> > +++ b/newlib/libc/unix/getlogin.c
> > @@ -16,9 +16,7 @@ getlogin ()
> >     extern char *ttyname ();
> >     char *tty;
> >
> > -  if (((tty = ttyname (0)) == 0)
> > -      || ((tty = ttyname (1)) == 0)
> > -      || ((tty = ttyname (2)) == 0))
> > +  if ((tty = ttyname (0)) == 0)
> >       return 0;
> >
> >     if ((utmp_fd = open (UTMP_FILE, O_RDONLY)) == -1)
> >
> >
> >
> > And a patch based on the comments of Torbjörn that checks all three fds
> > before returning NULL:
> >
> > diff --git a/newlib/libc/unix/getlogin.c b/newlib/libc/unix/getlogin.c
> > index da4f47a95..5a3f172e7 100644
> > --- a/newlib/libc/unix/getlogin.c
> > +++ b/newlib/libc/unix/getlogin.c
> > @@ -16,10 +16,10 @@ getlogin ()
> >     extern char *ttyname ();
> >     char *tty;
> >
> > -  if (((tty = ttyname (0)) == 0)
> > -      || ((tty = ttyname (1)) == 0)
> > -      || ((tty = ttyname (2)) == 0))
> > -    return 0;
> > +  if ((tty = ttyname (0)) == 0)
> > +      if ((tty = ttyname (1)) == 0)
> > +          if ((tty = ttyname (2)) == 0)
> > +              return 0;
> >
> >     if ((utmp_fd = open (UTMP_FILE, O_RDONLY)) == -1)
> >       return 0;
> >
> >
> > Any thoughts?
> > Thanks.
> >
> >
> > On 7/13/23 18:25, Torbjorn SVENSSON wrote:
> >
> > > I took a sneak peak at how glibc does this and there is this comment:
> > >
> > >    /* Get name of tty connected to fd 0.  Return NULL if not a tty or
> > >       if fd 0 isn't open.  Note that a lot of documentation says that
> > >       getlogin() is based on the controlling terminal---what they
> > >       really mean is "the terminal connected to standard input".  The
> > >       getlogin() implementation of DEC Unix, SunOS, Solaris, HP-UX all
> > >       return NULL if fd 0 has been closed, so this is the compatible
> > >       thing to do.  Note that ttyname(open("/dev/tty")) on those
> > >       systems returns /dev/tty, so that is not a possible solution for
> > >       getlogin().  */
> > >
> > > Based on this comment, I guess it would be sane to drop the check on
> > > stdout and stderr, but it would have the consequence that you are not
> > > able to pipe some data on stdin to the application that calls getlogin
> > > as it would fail in that scenario.
> > >
> > > I'm not a maintainer of newlib so I don't really have anything to say
> > > about what path you decide to go.
> >
> > --
> > Jordi Sanfeliu
> > FIBRANET Network Services Provider
> > https://www.fibranet.cat
> >
> >


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-12 17:33 [PATCH] Fix getlogin() to check only stdin to get a valid tty Jordi Sanfeliu
  2023-07-12 18:50 ` Torbjorn SVENSSON
@ 2023-07-17 19:06 ` Jeff Johnston
  2023-07-18  5:57   ` Jordi Sanfeliu
  2023-07-18  7:08   ` Jordi Sanfeliu
  1 sibling, 2 replies; 15+ messages in thread
From: Jeff Johnston @ 2023-07-17 19:06 UTC (permalink / raw)
  To: Jordi Sanfeliu; +Cc: newlib

[-- Attachment #1: Type: text/plain, Size: 1876 bytes --]

Original patch pushed, thanks.

-- Jeff J.

On Wed, Jul 12, 2023 at 1:34 PM Jordi Sanfeliu via Newlib <
newlib@sourceware.org> wrote:

> Hello,
>
> In my hobby OS [1] which uses Newlib C as its libc, I noticed that the
> GNU command 'logname' does output nothing when it is redirected or pipe'd.
>
> The current getlogin() implementation [2] forces the three primary file
> descriptors (stdin, stdout and stderr) to be a valid tty before checking
> the utmp file, otherwise it returns NULL. This makes impossible to
> redirect (to a file or to a pipe), the output of a program that is using
> this function because one of its file descriptors won't be a tty.
>
> See:
>
> # cat test.c
> #include <stdio.h>
>
> int main(void)
> {
>         char *user;
>
>         if(user = getlogin()) {
>                 printf("%s\n", user);
>         }
>
>         return 0;
> }
>
> # ./test
> root
> # ./test > xx
> # cat xx
> # ./test | cat
> #
>
> To fix this, I thought that only checking if stdin is a valid tty would
> be enough.
>
> Does this sound reasonable to you?
> Thanks.
>
>
>
> diff --git a/newlib/libc/unix/getlogin.c b/newlib/libc/unix/getlogin.c
> index da4f47a95..e646bcb08 100644
> --- a/newlib/libc/unix/getlogin.c
> +++ b/newlib/libc/unix/getlogin.c
> @@ -16,9 +16,7 @@ getlogin ()
>     extern char *ttyname ();
>     char *tty;
>
> -  if (((tty = ttyname (0)) == 0)
> -      || ((tty = ttyname (1)) == 0)
> -      || ((tty = ttyname (2)) == 0))
> +  if ((tty = ttyname (0)) == 0)
>       return 0;
>
>     if ((utmp_fd = open (UTMP_FILE, O_RDONLY)) == -1)
>
>
> 1. https://www.fiwix.org
> 2.
>
> https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/unix/getlogin.c;hb=HEAD
>
> --
> Jordi Sanfeliu
> FIBRANET Network Services Provider
> https://www.fibranet.cat
>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-17 19:06 ` Jeff Johnston
@ 2023-07-18  5:57   ` Jordi Sanfeliu
  2023-07-18  7:08   ` Jordi Sanfeliu
  1 sibling, 0 replies; 15+ messages in thread
From: Jordi Sanfeliu @ 2023-07-18  5:57 UTC (permalink / raw)
  To: Jeff Johnston; +Cc: newlib

Thank you very much.


On 7/17/23 21:06, Jeff Johnston wrote:
> Original patch pushed, thanks.
> 
> -- Jeff J.
> 


-- 
Jordi Sanfeliu
FIBRANET Network Services Provider
https://www.fibranet.cat

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-17 19:06 ` Jeff Johnston
  2023-07-18  5:57   ` Jordi Sanfeliu
@ 2023-07-18  7:08   ` Jordi Sanfeliu
  2023-07-18 17:44     ` Jeff Johnston
  1 sibling, 1 reply; 15+ messages in thread
From: Jordi Sanfeliu @ 2023-07-18  7:08 UTC (permalink / raw)
  To: Jeff Johnston; +Cc: newlib

Hello Jeff,

I'm reviewing the patch you applied to getlogin.c and it seems to me 
that there is an extra opening parenthesis.

You forgot the diff line:

  +  if ((tty = ttyname (0)) == 0)

Can you confirm it?

Regards.



On 7/17/23 21:06, Jeff Johnston wrote:
> Original patch pushed, thanks.
> 
> -- Jeff J.
> 

-- 
Jordi Sanfeliu
FIBRANET Network Services Provider
https://www.fibranet.cat

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-18  7:08   ` Jordi Sanfeliu
@ 2023-07-18 17:44     ` Jeff Johnston
  2023-07-18 18:59       ` Jordi Sanfeliu
  0 siblings, 1 reply; 15+ messages in thread
From: Jeff Johnston @ 2023-07-18 17:44 UTC (permalink / raw)
  To: Jordi Sanfeliu; +Cc: newlib

[-- Attachment #1: Type: text/plain, Size: 663 bytes --]

Yes, sorry.  Your patch didn't apply so I quickly manually changed it and
messed it up.
Fix applied.

-- Jeff J.

On Tue, Jul 18, 2023 at 3:08 AM Jordi Sanfeliu <jordi@fibranet.cat> wrote:

> Hello Jeff,
>
> I'm reviewing the patch you applied to getlogin.c and it seems to me
> that there is an extra opening parenthesis.
>
> You forgot the diff line:
>
>   +  if ((tty = ttyname (0)) == 0)
>
> Can you confirm it?
>
> Regards.
>
>
>
> On 7/17/23 21:06, Jeff Johnston wrote:
> > Original patch pushed, thanks.
> >
> > -- Jeff J.
> >
>
> --
> Jordi Sanfeliu
> FIBRANET Network Services Provider
> https://www.fibranet.cat
>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Fix getlogin() to check only stdin to get a valid tty
  2023-07-18 17:44     ` Jeff Johnston
@ 2023-07-18 18:59       ` Jordi Sanfeliu
  0 siblings, 0 replies; 15+ messages in thread
From: Jordi Sanfeliu @ 2023-07-18 18:59 UTC (permalink / raw)
  To: Jeff Johnston; +Cc: newlib

Perfect!


On 7/18/23 19:44, Jeff Johnston wrote:
> Yes, sorry.  Your patch didn't apply so I quickly manually changed it 
> and messed it up.
> Fix applied.
> 
> -- Jeff J.

-- 
Jordi Sanfeliu
FIBRANET Network Services Provider
https://www.fibranet.cat

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2023-07-18 18:59 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-12 17:33 [PATCH] Fix getlogin() to check only stdin to get a valid tty Jordi Sanfeliu
2023-07-12 18:50 ` Torbjorn SVENSSON
2023-07-12 20:06   ` Brian Inglis
2023-07-13 16:26     ` Torbjorn SVENSSON
2023-07-13  8:06   ` Jordi Sanfeliu
2023-07-13 16:25     ` Torbjorn SVENSSON
2023-07-13 16:57       ` Jordi Sanfeliu
2023-07-13 19:01         ` Jeff Johnston
2023-07-17  7:54           ` Corinna Vinschen
2023-07-13 21:12         ` Stefan Tauner
2023-07-17 19:06 ` Jeff Johnston
2023-07-18  5:57   ` Jordi Sanfeliu
2023-07-18  7:08   ` Jordi Sanfeliu
2023-07-18 17:44     ` Jeff Johnston
2023-07-18 18:59       ` Jordi Sanfeliu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).