diff --git a/fs/fcntl.c b/fs/fcntl.c
index 7a4d5a0..232a781 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -136,7 +136,7 @@ int dupfd(struct file *file, unsigned int start)
 
 EXPORT_SYMBOL_GPL(dupfd);
 
-asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
+static long do_dup3(unsigned int oldfd, unsigned int newfd, int flags)
 {
 	int err = -EBADF;
 	struct file * file, *tofree;
@@ -174,7 +174,10 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
 
 	files->fd[newfd] = file;
 	FD_SET(newfd, files->open_fds);
-	FD_CLR(newfd, files->close_on_exec);
+	if (flags & O_CLOEXEC)
+		FD_SET(newfd, files->close_on_exec);
+	else
+		FD_CLR(newfd, files->close_on_exec);
 	spin_unlock(&files->file_lock);
 
 	if (tofree)
@@ -191,8 +194,24 @@ out_fput:
 	fput(file);
 	goto out;
 }
+
+asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
+{
+	return do_dup3(oldfd, newfd, 0);
+}
 EXPORT_SYMBOL(sys_dup2);
 
+asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
+{
+	if ((flags & ~O_CLOEXEC) != 0)
+		return -EINVAL;
+
+	if (unlikely(oldfd == newfd))
+		return -EINVAL;
+
+	return do_dup3(oldfd, newfd, flags);
+}
+
 asmlinkage long sys_dup(unsigned int fildes)
 {
 	int ret = -EBADF;
