2008-10-23 22:29:50 +02:00
|
|
|
#!/usr/bin/perl
|
|
|
|
package IkiWiki::Receive;
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
use IkiWiki;
|
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub getuser () {
|
2008-10-24 21:47:42 +02:00
|
|
|
my $user=(getpwuid(exists $ENV{CALLER_UID} ? $ENV{CALLER_UID} : $<))[0];
|
2008-10-23 22:29:50 +02:00
|
|
|
if (! defined $user) {
|
|
|
|
error("cannot determine username for $<");
|
|
|
|
}
|
|
|
|
return $user;
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-10-23 22:29:50 +02:00
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub trusted () {
|
2008-10-23 22:29:50 +02:00
|
|
|
my $user=getuser();
|
|
|
|
return ! ref $config{untrusted_committers} ||
|
|
|
|
! grep { $_ eq $user } @{$config{untrusted_committers}};
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-10-23 22:29:50 +02:00
|
|
|
|
2009-09-10 22:09:19 +02:00
|
|
|
sub genwrapper () {
|
2008-10-26 19:03:18 +01:00
|
|
|
# Test for commits from untrusted committers in the wrapper, to
|
2009-09-10 22:09:19 +02:00
|
|
|
# avoid starting ikiwiki proper at all for trusted commits.
|
2008-10-26 19:03:18 +01:00
|
|
|
|
|
|
|
my $ret=<<"EOF";
|
|
|
|
{
|
|
|
|
int u=getuid();
|
2017-09-30 18:14:34 +02:00
|
|
|
/* 3 characters per byte is certainly enough */
|
|
|
|
char uid_string[sizeof(u) * 3 + 1];
|
2008-10-26 19:03:18 +01:00
|
|
|
EOF
|
|
|
|
$ret.="\t\tif ( ".
|
|
|
|
join("&&", map {
|
|
|
|
my $uid=getpwnam($_);
|
|
|
|
if (! defined $uid) {
|
|
|
|
error(sprintf(gettext("cannot determine id of untrusted committer %s"), $_));
|
|
|
|
}
|
|
|
|
"u != $uid";
|
|
|
|
} @{$config{untrusted_committers}}).
|
Consume all stdin when rcs_receive short-circuits, to avoid git SIPIPE race.
We had a weird problem where, after moving to a new, faster server,
"git push" would sometimes fail like this:
Unpacking objects: 100% (3/3), done.
fatal: The remote end hung up unexpectedly
fatal: The remote end hung up unexpectedly
What turned out to be going on was that git-receive-pack was dying due
to an uncaught SIGPIPE. The SIGPIPE occurred when it tried to write to
the pre-receive hook's stdin. The pre-receive hook, in this case, was
able to do all the checks it needed to do without the input, and so did
exit(0) without consuming it.
Apparently that causes a race. Most of the time, git forks the hook,
writes output to the hook, and then the hook runs, ignores it, and exits.
But sometimes, on our new faster server, git forked the hook, and it
ran, and exited, before git got around to writing to it, resulting in
the SIGPIPE.
write(7, "c9f98c67d70a1cfeba382ec27d87644a"..., 100) = -1 EPIPE (Broken
pipe)
--- SIGPIPE (Broken pipe) @ 0 (0) ---
I think git should ignore SIGPIPE when writing to hooks. Otherwise,
hooks may have to go out of their way to consume all input, and as I've
seen, the races when they fail to do this can lurk undiscovered.
I have written to the git mailing list about this.
As a workaround, consume all stdin before exiting.
2011-12-05 20:17:01 +01:00
|
|
|
") {\n";
|
2009-09-10 22:09:19 +02:00
|
|
|
|
|
|
|
|
2008-10-26 19:03:18 +01:00
|
|
|
$ret.=<<"EOF";
|
Consume all stdin when rcs_receive short-circuits, to avoid git SIPIPE race.
We had a weird problem where, after moving to a new, faster server,
"git push" would sometimes fail like this:
Unpacking objects: 100% (3/3), done.
fatal: The remote end hung up unexpectedly
fatal: The remote end hung up unexpectedly
What turned out to be going on was that git-receive-pack was dying due
to an uncaught SIGPIPE. The SIGPIPE occurred when it tried to write to
the pre-receive hook's stdin. The pre-receive hook, in this case, was
able to do all the checks it needed to do without the input, and so did
exit(0) without consuming it.
Apparently that causes a race. Most of the time, git forks the hook,
writes output to the hook, and then the hook runs, ignores it, and exits.
But sometimes, on our new faster server, git forked the hook, and it
ran, and exited, before git got around to writing to it, resulting in
the SIGPIPE.
write(7, "c9f98c67d70a1cfeba382ec27d87644a"..., 100) = -1 EPIPE (Broken
pipe)
--- SIGPIPE (Broken pipe) @ 0 (0) ---
I think git should ignore SIGPIPE when writing to hooks. Otherwise,
hooks may have to go out of their way to consume all input, and as I've
seen, the races when they fail to do this can lurk undiscovered.
I have written to the git mailing list about this.
As a workaround, consume all stdin before exiting.
2011-12-05 20:17:01 +01:00
|
|
|
/* Trusted user.
|
|
|
|
* Consume all stdin before exiting, as git may
|
|
|
|
* otherwise be unhappy. */
|
|
|
|
char buf[256];
|
|
|
|
while (read(0, &buf, 256) != 0) {}
|
|
|
|
exit(0);
|
|
|
|
}
|
2017-09-30 18:14:34 +02:00
|
|
|
snprintf(uid_string, sizeof(uid_string), "%i", u);
|
|
|
|
addenv("CALLER_UID", uid_string);
|
2008-10-26 19:03:18 +01:00
|
|
|
}
|
|
|
|
EOF
|
|
|
|
return $ret;
|
2008-12-17 21:22:16 +01:00
|
|
|
}
|
2008-10-26 19:03:18 +01:00
|
|
|
|
2008-12-17 21:22:16 +01:00
|
|
|
sub test () {
|
2008-10-23 22:29:50 +02:00
|
|
|
exit 0 if trusted();
|
2010-10-01 06:06:00 +02:00
|
|
|
|
2008-10-24 21:47:42 +02:00
|
|
|
IkiWiki::lockwiki();
|
|
|
|
IkiWiki::loadindex();
|
2010-10-01 06:06:00 +02:00
|
|
|
|
2008-10-23 22:29:50 +02:00
|
|
|
# Dummy up a cgi environment to use when calling check_canedit
|
|
|
|
# and friends.
|
|
|
|
eval q{use CGI};
|
|
|
|
error($@) if $@;
|
|
|
|
my $cgi=CGI->new;
|
2008-10-24 21:47:42 +02:00
|
|
|
|
|
|
|
# And dummy up a session object.
|
2008-10-23 22:29:50 +02:00
|
|
|
require IkiWiki::CGI;
|
|
|
|
my $session=IkiWiki::cgi_getsession($cgi);
|
2008-10-24 00:05:12 +02:00
|
|
|
$session->param("name", getuser());
|
2008-10-24 21:47:42 +02:00
|
|
|
# Make sure whatever user was authed is in the
|
|
|
|
# userinfo db.
|
|
|
|
require IkiWiki::UserInfo;
|
|
|
|
if (! IkiWiki::userinfo_get($session->param("name"), "regdate")) {
|
|
|
|
IkiWiki::userinfo_setall($session->param("name"), {
|
|
|
|
email => "",
|
|
|
|
password => "",
|
|
|
|
regdate => time,
|
|
|
|
}) || error("failed adding user");
|
|
|
|
}
|
2008-10-23 22:29:50 +02:00
|
|
|
|
2010-10-23 21:25:29 +02:00
|
|
|
IkiWiki::check_canchange(
|
2010-10-09 00:06:38 +02:00
|
|
|
cgi => $cgi,
|
2010-10-04 22:52:52 +02:00
|
|
|
session => $session,
|
|
|
|
changes => [IkiWiki::rcs_receive()]
|
|
|
|
);
|
2010-10-01 06:06:00 +02:00
|
|
|
exit 0;
|
|
|
|
}
|
|
|
|
|
2008-10-23 22:29:50 +02:00
|
|
|
1
|