[PATCH] sanitize unshare_files/reset_files_struct

* let unshare_files() give caller the displaced files_struct
* don't bother with grabbing reference only to drop it in the
  caller if it hadn't been shared in the first place
* in that form unshare_files() is trivially implemented via
  unshare_fd(), so we eliminate the duplicate logics in fork.c
* reset_files_struct() is not just only called for current;
  it will break the system if somebody ever calls it for anything
  else (we can't modify ->files of somebody else).  Lose the
  task_struct * argument.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
diff --git a/fs/exec.c b/fs/exec.c
index 4755430..b152029 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1269,19 +1269,13 @@
 	struct linux_binprm *bprm;
 	struct file *file;
 	unsigned long env_p;
-	struct files_struct *files;
+	struct files_struct *displaced;
 	int retval;
 
-	files = current->files;
-	retval = unshare_files();
+	retval = unshare_files(&displaced);
 	if (retval)
 		goto out_ret;
 
-	if (files == current->files) {
-		put_files_struct(files);
-		files = NULL;
-	}
-
 	retval = -ENOMEM;
 	bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
 	if (!bprm)
@@ -1340,8 +1334,8 @@
 		security_bprm_free(bprm);
 		acct_update_integrals(current);
 		kfree(bprm);
-		if (files)
-			put_files_struct(files);
+		if (displaced)
+			put_files_struct(displaced);
 		return retval;
 	}
 
@@ -1363,8 +1357,8 @@
 	kfree(bprm);
 
 out_files:
-	if (files)
-		reset_files_struct(current, files);
+	if (displaced)
+		reset_files_struct(displaced);
 out_ret:
 	return retval;
 }