如何找到进程启动时使用的原始用户名?

发布于 2024-08-25 01:30:39 字数 510 浏览 6 评论 0原文

有一个 perl 脚本需要以 root 身份运行,但我们必须确保运行该脚本的用户最初没有以用户“foo”身份登录,因为它将在脚本过程中被删除。

那么,我如何查明自登录以来可能已多次起诉的用户是否在该链中的任何时间都没有模拟过“foo”?

我发现一个有趣的 perl 脚本,它调用以下两个 shell 脚本,但我认为这只适用于 Solaris。

my $shell_parent = 
`ps -ef | grep -v grep | awk \'{print \$2\" \"\$3}\' | egrep \"^@_\" | awk \'{print \$2}'`;

my $parent_owner = 
`ps -ef | grep -v grep | awk \'{print \$1\" \"\$2}\' | grep @_ | awk \'{print \$1}\'`;

这需要在 Linux 和 Solaris 上工作,我宁愿消除对 shell 的重复调用,并将整个事情保留在 Perl 中。

There is a perl script that needs to run as root but we must make sure the user who runs the script did not log-in originally as user 'foo' as it will be removed during the script.

So how can I find out if the user, who might have su-ed several times since she logged in has not impersonated 'foo' at any time in that chain?

I found an interesting perl script that was calling the following two shell scripts, but I think that would only work on Solaris.

my $shell_parent = 
`ps -ef | grep -v grep | awk \'{print \$2\" \"\$3}\' | egrep \"^@_\" | awk \'{print \$2}'`;

my $parent_owner = 
`ps -ef | grep -v grep | awk \'{print \$1\" \"\$2}\' | grep @_ | awk \'{print \$1}\'`;

This needs to work on both Linux and Solaris and I'd rather eliminate the repeated calls to he the shell and keep the whole thing in Perl.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蒗幽 2024-09-01 01:30:39

快速而肮脏(仅限 UNIX):

my $user = (split /\s/,`who am i`)[0];

who am i 命令返回 TTY 的所有者 - 即您登录时的身份。

如果您想在纯 Perl 中执行此操作:

use POSIX;
my $tty = POSIX::ttyname(1); # The tty we are running in
my $uid = (stat $tty)[4];    # The owner uid of that tty
my $user = getpwuid($uid);   # The user with that uid

这将返回正确的用户,即使在多次 su 之后。这通常会让您(经验不足的)系统管理员感到害怕。

Quick and dirty and (UNIX only):

my $user = (split /\s/,`who am i`)[0];

The who am i command returns the owner of the TTY - i.e. who you were when you logged in.

If you want to do this in pure perl:

use POSIX;
my $tty = POSIX::ttyname(1); # The tty we are running in
my $uid = (stat $tty)[4];    # The owner uid of that tty
my $user = getpwuid($uid);   # The user with that uid

This will return the correct user, even after multiple su's. This usually freaks out your (less experienced) sysadmins.

忆悲凉 2024-09-01 01:30:39

这是一个检查直接 setuid 更改的 Perl 程序:

#! /usr/bin/perl

sub callingUser() {
    my ($login, $pass, $uid, $gid) = getpwuid(
lt;);
    return $login;
}

sub effectiveUser() {
    my ($login, $pass, $uid, $gid) = getpwuid(
gt;);
    return $login;
}

printf("Real user name: %s\n", effectiveUser());
printf("Calling user name: %s\n", callingUser());

但是既然您提到 setuid 更改可能以前发生过,您可能必须解析 ps 的输出:我将使用以下命令来执行此操作。该命令仅使用 POSIX 中定义的功能,所以我希望它是可移植到各种系统:

ps -e -o pid,ppid,user,ruser

Here's a Perl program that checks for direct setuid change:

#! /usr/bin/perl

sub callingUser() {
    my ($login, $pass, $uid, $gid) = getpwuid(
lt;);
    return $login;
}

sub effectiveUser() {
    my ($login, $pass, $uid, $gid) = getpwuid(
gt;);
    return $login;
}

printf("Real user name: %s\n", effectiveUser());
printf("Calling user name: %s\n", callingUser());

But since you mentioned that the setuid change may have occured anytime before, you probably have to parse the output of ps: I would do it using the following command. This command only uses features defined in POSIX, so I hope it is portable to all kinds of systems:

ps -e -o pid,ppid,user,ruser
苍暮颜 2024-09-01 01:30:39

也许下面的就是你想要的。函数hasBeenUser读取进程表,然后沿着从当前进程到父进程的进程链。如果途中的任何进程的 userreal user 字段等于所讨论的用户名,则该函数返回一个非零值。

#! /usr/bin/perl

sub hasBeenUser($) {
        my ($username) = @_;

        my $procs = {};
        open(PS, "ps -e -o pid,ppid,user,ruser |") or die;
        while (defined(my $line = <PS>)) {
                next unless $line =~ m"^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+$";
                my ($pid, $ppid, $user, $ruser) = (int($1), int($2), $3, $4);
                $procs->{$pid} = [$pid, $ppid, $user, $ruser];
        }
        close(PS) or die;

        my $pid = $;
        while (exists($procs->{$pid})) {
                my $proc = $procs->{$pid};
                delete $procs->{$pid}; # don't risk ending in an endless loop.
                warn "D: checking process $pid\n";
                if ($proc->[2] eq $username || $proc[3] eq $username) {
                        warn "E: process $pid was called by $username.\n";
                        return 1;
                }
                last if $pid < 2;
                $pid = $proc->[1];
        }
        return 0;
}

hasBeenUser("del"); # should return 0
hasBeenUser("root"); # should return nonzero

Maybe the following is what you want. The function hasBeenUser reads the process table and then follows the process chain from the current process down the parent process. If any of the processes on the way has a user or real user field equal to the username in question, the function returns a nonzero value.

#! /usr/bin/perl

sub hasBeenUser($) {
        my ($username) = @_;

        my $procs = {};
        open(PS, "ps -e -o pid,ppid,user,ruser |") or die;
        while (defined(my $line = <PS>)) {
                next unless $line =~ m"^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+$";
                my ($pid, $ppid, $user, $ruser) = (int($1), int($2), $3, $4);
                $procs->{$pid} = [$pid, $ppid, $user, $ruser];
        }
        close(PS) or die;

        my $pid = $;
        while (exists($procs->{$pid})) {
                my $proc = $procs->{$pid};
                delete $procs->{$pid}; # don't risk ending in an endless loop.
                warn "D: checking process $pid\n";
                if ($proc->[2] eq $username || $proc[3] eq $username) {
                        warn "E: process $pid was called by $username.\n";
                        return 1;
                }
                last if $pid < 2;
                $pid = $proc->[1];
        }
        return 0;
}

hasBeenUser("del"); # should return 0
hasBeenUser("root"); # should return nonzero
星星的軌跡 2024-09-01 01:30:39

当从 mc 调用脚本时(至少在我们的 RHEL 中),我发现了一个极端情况,这导致 who am i 不输出任何内容。为了避免这种情况,我在 bash 中生成了以下一行代码:

REALUSERNAME=$(ps uhp `ps -AjH | grep \`ps -u $USER fh | awk '{ print $0; if(index($0, "ps -u $USER fh")) exit 0;}' | tac | awk '{if(!index($0, "\\\\\_")){print $1; exit 0;}}'\` | awk '{print $3}'` | awk '{print $1}')

本质上,这会在 ps -u $USER fh 的树输出上向后行走,然后在最上面的用户名列上进行裁剪。

欢迎思考,更好的解决方案:-)

I recognized a corner case when calling scripts from mc (at least in our RHEL's), which results that the who am i does not output anything. To circumvent that, I produced the following one-liner in bash:

REALUSERNAME=$(ps uhp `ps -AjH | grep \`ps -u $USER fh | awk '{ print $0; if(index($0, "ps -u $USER fh")) exit 0;}' | tac | awk '{if(!index($0, "\\\\\_")){print $1; exit 0;}}'\` | awk '{print $3}'` | awk '{print $1}')

Essentially, this walks backwards on the tree output of ps -u $USER fh and then crops on the topmost username column.

Thoughts, better solutions are welcome :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文