Skip to content

Commit

Permalink
patch - Remove RCS and SCCS auto-checkout support
Browse files Browse the repository at this point in the history
* Remove stale RCS and SCCS support which involves the patch(1) program
  constructing a system() command using filename data supplied from the
  file.  DragonFly deems this to be too dangerous, quoted or not.

Security: CVE-2015-1416
Reported-by: Xin Li, Martin Natano
  • Loading branch information
Matthew Dillon committed Jul 25, 2015
1 parent d564b91 commit 05172c8
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 76 deletions.
2 changes: 0 additions & 2 deletions usr.bin/patch/common.h
Expand Up @@ -46,8 +46,6 @@
#define SCCSDIFF "get -p %s | diff - %s >/dev/null"

#define RCSSUFFIX ",v"
#define CHECKOUT "co -l %s"
#define RCSDIFF "rcsdiff %s > /dev/null"

#define ORIGEXT ".orig"
#define REJEXT ".rej"
Expand Down
74 changes: 7 additions & 67 deletions usr.bin/patch/inp.c
Expand Up @@ -133,7 +133,7 @@ static bool
plan_a(const char *filename)
{
int ifd, statfailed;
char *p, *s, lbuf[INITLINELEN];
char *p, *s;
struct stat filestat;
ptrdiff_t sz;
size_t i;
Expand Down Expand Up @@ -165,78 +165,18 @@ plan_a(const char *filename)
}
if (statfailed && check_only)
fatal("%s not found, -C mode, can't probe further\n", filename);
/* For nonexistent or read-only files, look for RCS or SCCS versions. */
/*
* For nonexistent or read-only files we no longer attempt to locate
* or checkout the file via RCS or SCCS, or do any call to system()
* whatsoever. CVE-2015-1416.
*/
if (statfailed ||
/* No one can write to it. */
(filestat.st_mode & 0222) == 0 ||
/* I can't write to it. */
((filestat.st_mode & 0022) == 0 && filestat.st_uid != getuid())) {
const char *cs = NULL, *filebase, *filedir;
struct stat cstat;
char *tmp_filename1, *tmp_filename2;

tmp_filename1 = strdup(filename);
tmp_filename2 = strdup(filename);
if (tmp_filename1 == NULL || tmp_filename2 == NULL)
fatal("strdupping filename");
filebase = basename(tmp_filename1);
filedir = dirname(tmp_filename2);

/* Leave room in lbuf for the diff command. */
s = lbuf + 20;

#define try(f, a1, a2, a3) \
(snprintf(s, buf_size - 20, f, a1, a2, a3), stat(s, &cstat) == 0)

if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
try("%s/RCS/%s%s", filedir, filebase, "") ||
try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
snprintf(buf, buf_size, CHECKOUT, filename);
snprintf(lbuf, sizeof lbuf, RCSDIFF, filename);
cs = "RCS";
} else if (try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) ||
try("%s/%s%s", filedir, SCCSPREFIX, filebase)) {
snprintf(buf, buf_size, GET, s);
snprintf(lbuf, sizeof lbuf, SCCSDIFF, s, filename);
cs = "SCCS";
} else if (statfailed)
if (statfailed)
fatal("can't find %s\n", filename);

free(tmp_filename1);
free(tmp_filename2);

/*
* else we can't write to it but it's not under a version
* control system, so just proceed.
*/
if (cs) {
if (!statfailed) {
if ((filestat.st_mode & 0222) != 0)
/* The owner can write to it. */
fatal("file %s seems to be locked "
"by somebody else under %s\n",
filename, cs);
/*
* It might be checked out unlocked. See if
* it's safe to check out the default version
* locked.
*/
if (verbose)
say("Comparing file %s to default "
"%s version...\n",
filename, cs);
if (system(lbuf))
fatal("can't check out file %s: "
"differs from default %s version\n",
filename, cs);
}
if (verbose)
say("Checking out file %s from %s...\n",
filename, cs);
if (system(buf) || stat(filename, &filestat))
fatal("can't check out file %s from %s\n",
filename, cs);
}
}
filemode = filestat.st_mode;
if (!S_ISREG(filemode))
Expand Down
10 changes: 3 additions & 7 deletions usr.bin/patch/patch.1
Expand Up @@ -481,14 +481,10 @@ file names or, for a non-context diff, the
file name, and choose the file name with the fewest path components,
the shortest basename, and the shortest total file name length (in that order).
.It
If no file exists,
.Nm
checks for the existence of the files in an SCCS or RCS directory
(using the appropriate prefix or suffix) using the criteria specified
above.
If found,
The
.Nm
will attempt to get or check out the file.
behavior of attempting to checkout RCS or SCCS files when the file is not
otherwise present is considered too dangerous and is no longer supported.
.It
If no suitable file was found to patch, the patch file is a context or
unified diff, and the old file was zero length, the new file name is
Expand Down

0 comments on commit 05172c8

Please sign in to comment.