Subject: bug#13447: ln "" foo gives misleading error message

From: Pádraig Brady <[email-masked]>
Date: Thu, 17 Jan 2013 13:09:20 +0000

On 01/15/2013 02:27 PM, Jim Meyering wrote:
> Pádraig Brady wrote:
> ...
>>> I could go either way.
>>> There is precedent, but it's such a corner case,
>>> it may not be worth the added code.
>>
>> given the confusion above, it might be worth the
>> clarification error message.
>
> Yes, I've demonstrated that rather well ;-)

Note to add the error robustly,
we'd have to check that ENOENT wasn't
in fact being generated for the link name.
That would involve stat()s and TOCTOU issues.

This Linux misinterpretation of POSIX has
been present for a long time as can be seen by
searching for sys_symlink in:

   http://repo.or.cz/w/davej-history.git/blame/HEAD:/fs/namei.c

I sent the attached path to the kernel list,
to see can we address it directly there.

thanks,
Pádraig.
>From a0d9810c5f4cf526430726f4e6aed88e8f9de1a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email-masked]>
Date: Thu, 17 Jan 2013 12:53:16 +0000
Subject: [PATCH] symlink: allow an empty target string
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

POSIX only states that ENOENT should be returned
if an empty string is specified for the link name.
In fact it states the link target...
"shall be treated only as a character string and
 shall not be validated as a pathname".

Signed-off-by: Pádraig Brady <[email-masked]>
---
 fs/namei.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 43a97ee..26dd264 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3533,12 +3533,13 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
 		int, newdfd, const char __user *, newname)
 {
 	int error;
+	int empty;
 	struct filename *from;
 	struct dentry *dentry;
 	struct path path;
 	unsigned int lookup_flags = 0;
 
-	from = getname(oldname);
+	from = getname_flags(oldname, LOOKUP_EMPTY, &empty);
 	if (IS_ERR(from))
 		return PTR_ERR(from);
 retry:
-- 
1.7.6.4