public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Pali Rohár" <pali@kernel.org>
To: Steve French <smfrench@gmail.com>
Cc: Steve French <sfrench@samba.org>,
	Paulo Alcantara <pc@manguebit.com>,
	Ronnie Sahlberg <ronniesahlberg@gmail.com>,
	linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 6/7] cifs: Validate content of native symlink
Date: Mon, 30 Sep 2024 22:00:26 +0200	[thread overview]
Message-ID: <20240930200026.efjs2v6ssqridcqx@pali> (raw)
In-Reply-To: <20240929221908.skkup4ds6ow2s77x@pali>

[-- Attachment #1: Type: text/plain, Size: 2733 bytes --]

Now I tested it. FSCTL_SET_REPARSE_POINT ioctl call on Windows accepts
also symlink path with zero characters. In attachment I'm sending simple
program which creates Windows relative symlink and accepts binary target
path via \xFF sequence. You can compile it with gcc/mingw option -municode.
So calling "set_reparse_symlink.exe symlink file\x00file" creates new
symlink which points to target path "file<nul>file".

On Monday 30 September 2024 00:19:08 Pali Rohár wrote:
> I think that via pike it could be possible or via windows application
> running locally (to create reparse point manually with prepared buffer
> with such content). I will check it later.
> 
> Just a side note: Windows NT kernel allows for object names any
> characters except backslash. For object names is not used nul-term
> string, but rather string with explicit length. So even a null character
> is a valid in a object name. NT NTFS driver has for file names more
> restrictions and null is not valid. But it does not mean that somebody
> can write own filesystem which allows null bytes in file names...
> And this design of explicit lengths is also in SMB, so NT kernel may
> export nul characters in symlink path buffers...
> 
> On Sunday 29 September 2024 16:48:46 Steve French wrote:
> > Is there any easy way to create such a symlink (with null in it)?
> > 
> > On Sun, Sep 29, 2024 at 1:51 PM Pali Rohár <pali@kernel.org> wrote:
> > >
> > > Check that buffer does not contain UTF-16 null codepoint
> > > because Linux cannot process symlink with null byte.
> > >
> > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > ---
> > >  fs/smb/client/reparse.c | 10 ++++++++++
> > >  1 file changed, 10 insertions(+)
> > >
> > > diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
> > > index 5a738f65b190..ca4f96c43508 100644
> > > --- a/fs/smb/client/reparse.c
> > > +++ b/fs/smb/client/reparse.c
> > > @@ -509,6 +509,16 @@ int smb2_parse_native_symlink(char **target, const char *buf, unsigned int len,
> > >         int rc;
> > >         int i;
> > >
> > > +       /*
> > > +        * Check that buffer does not contain UTF-16 null codepoint
> > > +        * because Linux cannot process symlink with null byte.
> > > +        */
> > > +       if (unicode && UniStrnlen((wchar_t *)buf, len/2) != len/2) {
> > > +               cifs_dbg(VFS, "srv returned null byte in native symlink target location\n");
> > > +               rc = -EIO;
> > > +               goto out;
> > > +       }
> > > +
> > >         smb_target = cifs_strndup_from_utf16(buf, len, unicode, cifs_sb->local_nls);
> > >         if (!smb_target) {
> > >                 rc = -ENOMEM;
> > > --
> > > 2.20.1
> > >
> > >
> > 
> > 
> > -- 
> > Thanks,
> > 
> > Steve

[-- Attachment #2: set_reparse_symlink.c --]
[-- Type: text/x-csrc, Size: 3199 bytes --]

#include <stdio.h>
#include <windows.h>
#include <ntdef.h>

int wmain(int argc, wchar_t *argv[]) {
  static BYTE reparse_data_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
  REPARSE_DATA_BUFFER *reparse_buffer = (REPARSE_DATA_BUFFER *)reparse_data_buffer;
  DWORD reparse_buffer_length;
  TOKEN_PRIVILEGES privileges;
  DWORD target_length;
  wchar_t *target;
  HANDLE handle;
  HANDLE token;
  BOOL success;
  DWORD i;

  if (argc != 3) {
    printf("Usage: %ls new_file target\n", argv[0]);
    return 1;
  }

  target = argv[2];
  for (i = 0, target_length = 0; target[i]; i++, target_length++) {
    if (target[i] == L'\\') {
      if (target[i+1] == L'\\') {
        target[target_length] = L'\\';
        i++;
        continue;
      } else if (target[i+1] == L'x' && target[i+2] >= L'0' && target[i+2] <= L'9' && target[i+3] >= L'0' && target[i+3] <= L'9') {
        target[target_length] = ((target[i+2]-L'0') << 4) | (target[i+3]-L'0');
        i += 3;
        continue;
      }
    }
    target[target_length] = target[i];
  }
  target_length *= sizeof(target[0]);

  reparse_buffer_length = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + target_length*2;
  if (reparse_buffer_length > MAXIMUM_REPARSE_DATA_BUFFER_SIZE) {
    printf("Target path is too long\n");
    return 1;
  }

  reparse_buffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;
  reparse_buffer->ReparseDataLength = reparse_buffer_length - REPARSE_DATA_BUFFER_HEADER_SIZE;
  reparse_buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
  reparse_buffer->SymbolicLinkReparseBuffer.SubstituteNameLength = target_length;
  reparse_buffer->SymbolicLinkReparseBuffer.PrintNameOffset = target_length;
  reparse_buffer->SymbolicLinkReparseBuffer.PrintNameLength = target_length;
  reparse_buffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE;
  memcpy(reparse_buffer->SymbolicLinkReparseBuffer.PathBuffer, target, target_length);
  memcpy(((BYTE*)reparse_buffer->SymbolicLinkReparseBuffer.PathBuffer)+target_length, target, target_length);

  if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) {
    if (LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &privileges.Privileges[0].Luid)) {
      privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
      privileges.PrivilegeCount = 1;
      AdjustTokenPrivileges(token, FALSE, &privileges, sizeof(privileges), NULL, NULL);
    }
    CloseHandle(token);
  }

  handle = CreateFileW(argv[1], FILE_WRITE_DATA, FILE_SHARE_VALID_FLAGS, NULL, OPEN_ALWAYS, FILE_FLAG_OPEN_REPARSE_POINT, NULL);
  if (handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_ACCESS_DENIED)
    handle = CreateFileW(argv[1], FILE_WRITE_DATA, FILE_SHARE_VALID_FLAGS, NULL, OPEN_ALWAYS, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
  if (handle == INVALID_HANDLE_VALUE) {
    printf("CreateFileW failed: %lu\n", GetLastError());
    return 1;
  }

  success = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, reparse_buffer, reparse_buffer_length, NULL, 0, NULL, NULL);
  CloseHandle(handle);
  if (!success) {
    printf("FSCTL_SET_REPARSE_POINT failed: %lu\n", GetLastError());
    return 1;
  }

  return 0;
}

  reply	other threads:[~2024-09-30 20:00 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-29 18:50 [PATCH 0/7] cifs: Improve support for native SMB symlinks Pali Rohár
2024-09-29 18:50 ` [PATCH 1/7] cifs: Rename smb2_get_reparse_inode to smb2_create_reparse_inode Pali Rohár
2024-09-29 21:16   ` Steve French
2024-09-29 22:05     ` Pali Rohár
2024-09-29 18:50 ` [PATCH 2/7] cifs: Improve creating native symlinks pointing to directory Pali Rohár
2024-09-29 21:54   ` Steve French
2024-09-29 22:11     ` Pali Rohár
2024-09-30 15:09   ` Paulo Alcantara
2024-09-30 17:17     ` Pali Rohár
2024-10-05 14:08       ` Pali Rohár
2024-09-29 18:50 ` [PATCH 3/7] cifs: Fix creating native symlinks pointing to current or parent directory Pali Rohár
2024-09-29 18:50 ` [PATCH 4/7] cifs: Fix parsing native symlinks relative to the export Pali Rohár
2024-09-29 18:50 ` [PATCH 5/7] cifs: Fix parsing native symlinks directory/file type Pali Rohár
2024-09-29 21:47   ` Steve French
2024-09-29 21:58     ` Pali Rohár
2024-09-29 18:50 ` [PATCH 6/7] cifs: Validate content of native symlink Pali Rohár
2024-09-29 21:48   ` Steve French
2024-09-29 22:19     ` Pali Rohár
2024-09-30 20:00       ` Pali Rohár [this message]
2024-09-29 18:50 ` [PATCH 7/7] cifs: Fix creating and resolving absolute NT-style symlinks Pali Rohár
2024-09-29 22:03 ` [PATCH 0/7] cifs: Improve support for native SMB symlinks Steve French
2024-10-05 14:07   ` Pali Rohár
2024-10-05 14:02 ` [PATCH v2 0/6] " Pali Rohár
2024-10-05 14:02   ` [PATCH v2 1/6] cifs: Improve creating native symlinks pointing to directory Pali Rohár
2024-10-05 14:02   ` [PATCH v2 2/6] cifs: Fix creating native symlinks pointing to current or parent directory Pali Rohár
2024-10-05 14:02   ` [PATCH v2 3/6] cifs: Fix parsing native symlinks relative to the export Pali Rohár
2024-10-05 14:02   ` [PATCH v2 4/6] cifs: Fix parsing native symlinks directory/file type Pali Rohár
2024-10-13 17:56     ` Steve French
2024-10-14  9:52       ` Pali Rohár
2024-10-15 14:30     ` [PATCH v3] " Pali Rohár
2024-12-09 18:02       ` Pali Rohár
2024-10-05 14:02   ` [PATCH v2 5/6] cifs: Validate content of native symlink Pali Rohár
2024-10-13  4:21     ` Steve French
2024-10-14  9:39       ` Pali Rohár
2024-10-05 14:03   ` [PATCH v2 6/6] cifs: Fix creating and resolving absolute NT-style symlinks Pali Rohár
2024-10-07  3:59     ` Steve French
2024-10-07 18:09       ` Pali Rohár
2024-12-09 17:58     ` Pali Rohár

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240930200026.efjs2v6ssqridcqx@pali \
    --to=pali@kernel.org \
    --cc=linux-cifs@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pc@manguebit.com \
    --cc=ronniesahlberg@gmail.com \
    --cc=sfrench@samba.org \
    --cc=smfrench@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox