Code: static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files,
		     rpmpsm psm, int nodigest, int *setmeta,
		     int * firsthardlink)
{
    int rc = 0;
    int numHardlinks = rpmfiFNlink(fi);

    if (numHardlinks > 1) {
 	/* Create first hardlinked file empty */
 	if (*firsthardlink < 0) {
 	    *firsthardlink = rpmfiFX(fi);
	    rc = expandRegular(fi, dest, psm, nodigest, 1);
 	} else {
 	    /* Create hard links for others */
 	    char *fn = rpmfilesFN(files, *firsthardlink);
	    rc = link(fn, dest);
	    if (rc < 0) {
		rc = RPMERR_LINK_FAILED;
	    }
	    free(fn);
	}
    }
    /* Write normal files or fill the last hardlinked (already
        existing) file with content */
     if (numHardlinks<=1) {
 	if (!rc)
	    rc = expandRegular(fi, dest, psm, nodigest, 0);
     } else if (rpmfiArchiveHasContent(fi)) {
 	if (!rc)
	    rc = expandRegular(fi, dest, psm, nodigest, 0);
 	*firsthardlink = -1;
     } else {
 	*setmeta = 0;
    }

    return rc;
}

Commit Message: Don't follow symlinks on file creation (CVE-2017-7501)

Open newly created files with O_EXCL to prevent symlink tricks.
When reopening hardlinks for writing the actual content, use append
mode instead. This is compatible with the write-only permissions but
is not destructive in case we got redirected to somebody elses file,
verify the target before actually writing anything.

As these are files with the temporary suffix, errors mean a local
user with sufficient privileges to break the installation of the package
anyway is trying to goof us on purpose, don't bother trying to mend it
(we couldn't fix the hardlink case anyhow) but just bail out.

Based on a patch by Florian Festi.
CWE ID: CWE-59
static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files,
		     rpmpsm psm, int nodigest, int *setmeta,
		     int * firsthardlink)
{
    int rc = 0;
    int numHardlinks = rpmfiFNlink(fi);

    if (numHardlinks > 1) {
 	/* Create first hardlinked file empty */
 	if (*firsthardlink < 0) {
 	    *firsthardlink = rpmfiFX(fi);
	    rc = expandRegular(fi, dest, psm, 1, nodigest, 1);
 	} else {
 	    /* Create hard links for others */
 	    char *fn = rpmfilesFN(files, *firsthardlink);
	    rc = link(fn, dest);
	    if (rc < 0) {
		rc = RPMERR_LINK_FAILED;
	    }
	    free(fn);
	}
    }
    /* Write normal files or fill the last hardlinked (already
        existing) file with content */
     if (numHardlinks<=1) {
 	if (!rc)
	    rc = expandRegular(fi, dest, psm, 1, nodigest, 0);
     } else if (rpmfiArchiveHasContent(fi)) {
 	if (!rc)
	    rc = expandRegular(fi, dest, psm, 0, nodigest, 0);
 	*firsthardlink = -1;
     } else {
 	*setmeta = 0;
    }

    return rc;
}
