aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2005-05-18 05:56:16 +0000
committerRob Landley <rob@landley.net>2005-05-18 05:56:16 +0000
commit5797c7f0ef93f3efd0ba6634640f9591716214e3 (patch)
tree76722f5b18215592a6b9c7c36693812df84cf3d8
parent1fb7961e081f43fcfdb12bc588cc294115841f9c (diff)
downloadbusybox-w32-5797c7f0ef93f3efd0ba6634640f9591716214e3.tar.gz
busybox-w32-5797c7f0ef93f3efd0ba6634640f9591716214e3.tar.bz2
busybox-w32-5797c7f0ef93f3efd0ba6634640f9591716214e3.zip
Doug Swarin pointed out a security bug in the -i option of sed.
While the permissions on the temp file are correct to prevent it from being maliciously mangled by passing strangers, (created with 600, opened O_EXCL, etc), the permissions on the _directory_ might not be, and we re-open the file to convert the filehandle to a FILE * (and automatically get an error message and exit if the directory's read-only or out of space or some such). This opens a potential race condition if somebody's using dnotify on the directory, deletes/renames the tempfile, and drops a symlink or something there. Somebody running sed -i as root in a world writeable directory could do damage. I dug up notes on an earlier discussion where we looked at the security implications of this (unfortunately on the #uclibc channel rather than email; I don't have a transcript, just notes-to-self) which pointed out that if the permissions on the directory allow other people's files to be deleted/renamed then the original file is vulnerable to sabotage anyway. However, there are two cases that discussion apparently didn't take into account: 1) Using another user's permissions to damage files in other directories you can't access (standard symlink attack). 2) Reading data another user couldn't otherwise access by having the new file belong to that other user. This patch uses fdopen to convert the filehandle into a FILE *, rather than reopening the file.
-rw-r--r--editors/sed.c17
1 files changed, 8 insertions, 9 deletions
diff --git a/editors/sed.c b/editors/sed.c
index 7950b9303..1b6ed2b0f 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -135,7 +135,7 @@ static sed_cmd_t sed_cmd_head;
135static sed_cmd_t *sed_cmd_tail = &sed_cmd_head; 135static sed_cmd_t *sed_cmd_tail = &sed_cmd_head;
136 136
137/* Linked list of append lines */ 137/* Linked list of append lines */
138static struct append_list { 138struct append_list {
139 char *string; 139 char *string;
140 struct append_list *next; 140 struct append_list *next;
141}; 141};
@@ -1187,10 +1187,7 @@ extern int sed_main(int argc, char **argv)
1187 * files were specified or '-' was specified, take input from stdin. 1187 * files were specified or '-' was specified, take input from stdin.
1188 * Otherwise, we process all the files specified. */ 1188 * Otherwise, we process all the files specified. */
1189 if (argv[optind] == NULL) { 1189 if (argv[optind] == NULL) {
1190 if(in_place) { 1190 if(in_place) bb_error_msg_and_die("Filename required for -i");
1191 fprintf(stderr,"sed: Filename required for -i\n");
1192 exit(1);
1193 }
1194 add_input_file(stdin); 1191 add_input_file(stdin);
1195 process_files(); 1192 process_files();
1196 } else { 1193 } else {
@@ -1206,14 +1203,16 @@ extern int sed_main(int argc, char **argv)
1206 if (file) { 1203 if (file) {
1207 if(in_place) { 1204 if(in_place) {
1208 struct stat statbuf; 1205 struct stat statbuf;
1206 int nonstdoutfd;
1207
1209 outname=bb_xstrndup(argv[i],strlen(argv[i])+6); 1208 outname=bb_xstrndup(argv[i],strlen(argv[i])+6);
1210 strcat(outname,"XXXXXX"); 1209 strcat(outname,"XXXXXX");
1211 mkstemp(outname); 1210 if(-1==(nonstdoutfd=mkstemp(outname)))
1212 nonstdout=bb_wfopen(outname,"w"); 1211 bb_error_msg_and_die("no temp file");
1212 nonstdout=fdopen(nonstdoutfd,"w");
1213 /* Set permissions of output file */ 1213 /* Set permissions of output file */
1214 fstat(fileno(file),&statbuf); 1214 fstat(fileno(file),&statbuf);
1215 fchmod(fileno(nonstdout),statbuf.st_mode); 1215 fchmod(nonstdoutfd,statbuf.st_mode);
1216 atexit(cleanup_outname);
1217 add_input_file(file); 1216 add_input_file(file);
1218 process_files(); 1217 process_files();
1219 fclose(nonstdout); 1218 fclose(nonstdout);