:: Re: [DNG] The show goes on: “su” c…
Αρχική Σελίδα
Delete this message
Reply to this message
Συντάκτης: Rainer Weikusat
Ημερομηνία:  
Προς: dng
Αντικείμενο: Re: [DNG] The show goes on: “su” command replacement merged into systemd on Fedora Rawhide
Laurent Bercot <ska-devel@???> writes:
> On 29/08/2015 14:43, Rainer Weikusat wrote:
>> 'su' is not a concept, it's a program.
>
> <grumble> Okay, let's clarify.
> A program is the implementation of an idea. The idea is often
> unwritten or unspoken, or forgotten, and people will only refer
> to the implementation; but good design always starts with the idea,
> the concept, of what the program is supposed to do.
>
> When Lennart says "su is a broken concept", he's saying "the
> concept behind the su program is not clear or well-defined, and
> it was not a good idea to implement it";


I completely understand that Poettering prefers to write something like
"su is a broken concept" when he really means "What this program does is
not what I'd like it to do and I'd like it to do things it doesn't do
and since it wasn't written by me, it's not working in the way it had
worked had I written the code." But "broken concept" doesn't really make
any sense: Since ideas don't work, they can't be 'broken', ie not or no
longer capable of working.

su is a program supposed to be installed setuid-0 and what it basically
does is

setuid(geteuid());
execlp("/bin/sh", "sh", (void *)0);

ie, it gets rid of any traces of the uid associated with the process
which invoked it and then replaces itself with a shell. In the usual way,
it then kept accumulating other features related to this simple task
which helped other people to get certain things done. It's (AFAIK) no
longer in active development, hence, the current feature set faithfully
mirrors whatever some people considered useful in the early 1990s. In
itself, this is a not a problem, it just means that su is more useful
for certain tasks and less useful for others. The program is certainly
not 'broken', either, as this would mean "the documented behaviour and
the actual behaviour differ in unintended ways".

Considering that 'concepts' can't be broken and that the program isn't
broken, the statement is actually pure posturing devoid of any meaning:
A somewhat technically sounding way to express "I don't care, bugger
off".

[...]

> As you're saying, the correct design is to separate the tasks
> that the su program accomplishes, if one doesn't need a full-
> environment root shell.


I wouldn't calls this "the correct design": It's a design I consider
advantageous because it avoids a situation where a certain program
'organically' acquires some odd feature set which can't be changed in
incompatible ways without affecting existing users and hence basically
turns into a development dead-end.

> But if a full-environment root shell is needed, logging in as
> root works. That's exactly what the "login" _concept_ is.


I'm not aware of any formal definition of "full-environment root shell"
beyond "what the result of logging in as root by interacting with the
following programs ..., ... and ... in the following way ...,
... happens to be". And I don't think such a formal definition would be
useful. OTOH, executing 'the shell of some user' such that it considers
itself a login shell, ie, processes the startup files such a shell is
supposed to process is useful just not a panacea.

Another tinygram doing that:

---------
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define DEFAULT_SHELL    "/bin/sh"


static char *get_shell(void)
{
    struct passwd *pwd;
    char *shell;


    shell = getenv("SHELL");
    if (shell && *shell) return shell;


    pwd = getpwuid(getuid());
    if (pwd && *pwd->pw_shell) return pwd->pw_shell;


    return DEFAULT_SHELL;
}


static char *get_shell_name(char *shell)
{
    char *p0, *p1, *name;


    p0 = p1 = shell;
    while (*p1) {
    if (*p1 == '/') p0 = p1 + 1;
    ++p1;
    }


    if (!*p0) {
    fprintf(stderr, "Don't know what to make of '%s'\n",
        shell);
    exit(1);
    }


    name = sbrk((p1 - p0) + 2);
    if (!name) {
    perror("sbrk");
    exit(1);
    }


    *name = '-';
    strcpy(name + 1, p0);


    return name;
}


int main(void)
{
    char *shell, *name;


    shell = get_shell();
    name = get_shell_name(shell);
    execl(shell, name, (void *)0);


    perror("execl");
    return 1;
}
------


Invoking this via sudo will result in an 'interactive' root login shell
insofar the shell itself is concerned.