diff -up cups-1.3.7/cups/file.c.CVE-2010-2431 cups-1.3.7/cups/file.c --- cups-1.3.7/cups/file.c.CVE-2010-2431 2007-09-17 21:35:54.000000000 +0100 +++ cups-1.3.7/cups/file.c 2010-10-26 11:04:54.101870517 +0100 @@ -8,7 +8,7 @@ * our own file functions allows us to provide transparent support of * gzip'd print files, PPD files, etc. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2010 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,7 @@ struct _cups_file_s /**** CUPS file st static ssize_t cups_compress(cups_file_t *fp, const char *buf, size_t bytes); #endif /* HAVE_LIBZ */ static ssize_t cups_fill(cups_file_t *fp); +static int cups_open(const char *filename, int mode); static ssize_t cups_read(cups_file_t *fp, char *buf, size_t bytes); static ssize_t cups_write(cups_file_t *fp, const char *buf, size_t bytes); @@ -811,7 +813,8 @@ cupsFileOpen(const char *filename, /* I switch (*mode) { case 'a' : /* Append file */ - fd = open(filename, O_RDWR | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY, 0666); + fd = cups_open(filename, + O_RDWR | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY); break; case 'r' : /* Read file */ @@ -819,7 +822,17 @@ cupsFileOpen(const char *filename, /* I break; case 'w' : /* Write file */ - fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_LARGEFILE | O_BINARY, 0666); + fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY); + if (fd < 0 && errno == ENOENT) + { + fd = cups_open(filename, + O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE | O_BINARY); + if (fd < 0 && errno == EEXIST) + fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY); + } + + if (fd >= 0) + ftruncate(fd, 0); break; case 's' : /* Read/write socket */ @@ -2019,6 +2032,87 @@ cups_fill(cups_file_t *fp) /* I - CUPS /* + * 'cups_open()' - Safely open a file for writing. + * + * We don't allow appending to directories or files that are hard-linked or + * symlinked. + */ + +static int /* O - File descriptor or -1 otherwise */ +cups_open(const char *filename, /* I - Filename */ + int mode) /* I - Open mode */ +{ + int fd; /* File descriptor */ + struct stat fileinfo; /* File information */ +#ifndef WIN32 + struct stat linkinfo; /* Link information */ +#endif /* !WIN32 */ + + + /* + * Open the file... + */ + + if ((fd = open(filename, mode, 0666)) < 0) + return (-1); + + /* + * Then verify that the file descriptor doesn't point to a directory or hard- + * linked file. + */ + + if (fstat(fd, &fileinfo)) + { + close(fd); + return (-1); + } + + if (fileinfo.st_nlink != 1) + { + close(fd); + errno = EPERM; + return (-1); + } + + if (S_ISDIR(fileinfo.st_mode)) + { + close(fd); + errno = EISDIR; + return (-1); + } + +#ifndef WIN32 + /* + * Then use lstat to determine whether the filename is a symlink... + */ + + if (lstat(filename, &linkinfo)) + { + close(fd); + return (-1); + } + + if (S_ISLNK(linkinfo.st_mode) || + fileinfo.st_dev != linkinfo.st_dev || + fileinfo.st_ino != linkinfo.st_ino || + fileinfo.st_nlink != linkinfo.st_nlink || + fileinfo.st_mode != linkinfo.st_mode) + { + /* + * Yes, don't allow! + */ + + close(fd); + errno = EPERM; + return (-1); + } +#endif /* !WIN32 */ + + return (fd); +} + + +/* * 'cups_read()' - Read from a file descriptor. */