xiaoxiang781216 commented on code in PR #19900:
URL: https://github.com/apache/nuttx/pull/19900#discussion_r3845742211


##########
fs/vfs/fs_chroot.c:
##########
@@ -0,0 +1,206 @@
+/****************************************************************************
+ * fs/vfs/fs_chroot.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/sched.h>
+
+#include "inode/inode.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: chroot_make_abspath
+ *
+ * Description:
+ *   Build the host absolute path of the directory inode returned by
+ *   inode_find(), including the mount-relative suffix when the jail is
+ *   inside a volume such as tmpfs.
+ *
+ * Input Parameters:
+ *   node    - Inode returned by inode_find()
+ *   relpath - Remaining path inside a mount, or NULL/empty
+ *   out     - Buffer that receives the absolute path
+ *   outlen  - Size of 'out' in bytes
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int chroot_make_abspath(FAR struct inode *node,
+                               FAR const char *relpath,
+                               FAR char *out, size_t outlen)
+{
+  size_t len;
+  int ret;
+
+  ret = inode_getpath(node, out, outlen);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  len = strlen(out);
+  while (len > 1 && out[len - 1] == '/')
+    {
+      out[--len] = '\0';
+    }
+
+  if (relpath != NULL && relpath[0] != '\0')
+    {
+      if (len > 1)
+        {
+          if (len + 1 + strlen(relpath) + 1 > outlen)
+            {
+              return -ENAMETOOLONG;
+            }
+
+          out[len++] = '/';
+          out[len] = '\0';
+        }
+
+      strlcat(out, relpath, outlen);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: chroot
+ *
+ * Description:
+ *   Cause the named directory to become the root directory, that is, the
+ *   starting point for path names beginning with '/'.
+ *
+ * Input Parameters:
+ *   path - Directory to use as the new root
+ *
+ * Returned Value:
+ *   0(OK) on success; -1(ERROR) on failure with errno set appropriately.
+ *
+ ****************************************************************************/
+
+int chroot(FAR const char *path)
+{
+  struct inode_search_s desc;
+  FAR struct tcb_s *rtcb;
+  FAR struct task_group_s *group;
+  FAR char *newroot;
+  char abspath[PATH_MAX];
+  struct stat buf;
+  int errcode;
+  int ret;
+
+  if (path == NULL || path[0] == '\0')
+    {
+      set_errno(ENOENT);
+      return ERROR;
+    }
+
+  rtcb = nxsched_self();
+  DEBUGASSERT(rtcb != NULL && rtcb->group != NULL);
+  group = rtcb->group;
+
+#ifdef CONFIG_SCHED_USER_IDENTITY
+  if (group->tg_euid != 0)
+    {
+      set_errno(EPERM);
+      return ERROR;
+    }
+#endif
+
+  ret = nx_stat(path, &buf, 1);
+  if (ret < 0)
+    {
+      set_errno(-ret);
+      return ERROR;
+    }
+
+  if (!S_ISDIR(buf.st_mode))
+    {
+      set_errno(ENOTDIR);
+      return ERROR;
+    }
+
+  SETUP_SEARCH(&desc, path, false);
+
+  ret = inode_find(&desc);
+  if (ret < 0)
+    {
+      errcode = -ret;
+      goto errout_with_search;
+    }
+
+  ret = chroot_make_abspath(desc.node, desc.relpath, abspath,
+                            sizeof(abspath));
+  inode_release(desc.node);
+  if (ret < 0)
+    {
+      errcode = -ret;
+      goto errout_with_search;
+    }
+
+  /* chroot("/") from the global root is a no-op (tg_root stays NULL). */
+
+  if (strcmp(abspath, "/") == 0)

Review Comment:
   but caller may change to no root before



##########
fs/inode/fs_inodesearch.c:
##########
@@ -193,6 +199,213 @@ static int _inode_linktarget(FAR struct inode *inode,
 }
 #endif
 
+#ifdef CONFIG_FS_CHROOT
+/****************************************************************************
+ * Name: inode_normalize_abs
+ *
+ * Description:
+ *   Normalize an absolute path into 'out': drop empty and "." segments,
+ *   collapse "..", and do not let the result become shorter than
+ *   'clamplen' bytes (the jail prefix).  The input is read once; each
+ *   segment is written directly into 'out'.
+ *
+ * Input Parameters:
+ *   in       - Absolute path to normalize.  Must begin with '/'.
+ *              Advanced across the string once; not used after return.
+ *   out      - Buffer that receives the normalized, NUL-terminated path.
+ *   outlen   - Size of 'out' in bytes.
+ *   clamplen - Minimum length to keep (strlen of the jail root, or 1
+ *              for "/").  ".." will not pop above this prefix.
+ *
+ * Returned Value:
+ *   OK (zero) on success.  A negated errno value is returned on
+ *   failure:
+ *
+ *     -EINVAL       - 'in' is NULL or does not start with '/'.
+ *     -ENAMETOOLONG - 'out' is too small, or the result does not fit.
+ *
+ ****************************************************************************/
+
+static int inode_normalize_abs(FAR const char *in, FAR char *out,
+                               size_t outlen, size_t clamplen)
+{
+  FAR char *dst;
+  FAR char *clamp;
+
+  if (in == NULL || *in != '/')
+    {
+      return -EINVAL;
+    }
+
+  if (outlen < 2)
+    {
+      return -ENAMETOOLONG;
+    }
+
+  if (clamplen < 1)
+    {
+      clamplen = 1;
+    }
+
+  dst = out;
+  *dst++ = '/';
+  in++;
+
+  while (*in == '/')
+    {
+      in++;
+    }
+
+  clamp = out + clamplen;
+
+  while (*in != '\0')
+    {
+      FAR const char *seg = in;
+      size_t seglen;
+
+      while (*in != '\0' && *in != '/')
+        {
+          in++;
+        }
+
+      seglen = (size_t)(in - seg);

Review Comment:
   remove the cast



##########
fs/vfs/fs_chroot.c:
##########
@@ -0,0 +1,206 @@
+/****************************************************************************
+ * fs/vfs/fs_chroot.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/sched.h>
+
+#include "inode/inode.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: chroot_make_abspath
+ *
+ * Description:
+ *   Build the host absolute path of the directory inode returned by
+ *   inode_find(), including the mount-relative suffix when the jail is
+ *   inside a volume such as tmpfs.
+ *
+ * Input Parameters:
+ *   node    - Inode returned by inode_find()
+ *   relpath - Remaining path inside a mount, or NULL/empty
+ *   out     - Buffer that receives the absolute path
+ *   outlen  - Size of 'out' in bytes
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int chroot_make_abspath(FAR struct inode *node,
+                               FAR const char *relpath,
+                               FAR char *out, size_t outlen)
+{
+  size_t len;
+  int ret;
+
+  ret = inode_getpath(node, out, outlen);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  len = strlen(out);
+  while (len > 1 && out[len - 1] == '/')
+    {
+      out[--len] = '\0';
+    }
+
+  if (relpath != NULL && relpath[0] != '\0')
+    {
+      if (len > 1)
+        {
+          if (len + 1 + strlen(relpath) + 1 > outlen)
+            {
+              return -ENAMETOOLONG;
+            }
+
+          out[len++] = '/';
+          out[len] = '\0';
+        }
+
+      strlcat(out, relpath, outlen);

Review Comment:
   strlcpy by len offset



##########
fs/inode/fs_inodesearch.c:
##########
@@ -193,6 +199,213 @@ static int _inode_linktarget(FAR struct inode *inode,
 }
 #endif
 
+#ifdef CONFIG_FS_CHROOT
+/****************************************************************************
+ * Name: inode_normalize_abs
+ *
+ * Description:
+ *   Normalize an absolute path into 'out': drop empty and "." segments,
+ *   collapse "..", and do not let the result become shorter than
+ *   'clamplen' bytes (the jail prefix).  The input is read once; each
+ *   segment is written directly into 'out'.
+ *
+ * Input Parameters:
+ *   in       - Absolute path to normalize.  Must begin with '/'.
+ *              Advanced across the string once; not used after return.
+ *   out      - Buffer that receives the normalized, NUL-terminated path.
+ *   outlen   - Size of 'out' in bytes.
+ *   clamplen - Minimum length to keep (strlen of the jail root, or 1
+ *              for "/").  ".." will not pop above this prefix.
+ *
+ * Returned Value:
+ *   OK (zero) on success.  A negated errno value is returned on
+ *   failure:
+ *
+ *     -EINVAL       - 'in' is NULL or does not start with '/'.
+ *     -ENAMETOOLONG - 'out' is too small, or the result does not fit.
+ *
+ ****************************************************************************/
+
+static int inode_normalize_abs(FAR const char *in, FAR char *out,
+                               size_t outlen, size_t clamplen)
+{
+  FAR char *dst;
+  FAR char *clamp;
+
+  if (in == NULL || *in != '/')
+    {
+      return -EINVAL;
+    }
+
+  if (outlen < 2)
+    {
+      return -ENAMETOOLONG;
+    }
+
+  if (clamplen < 1)
+    {
+      clamplen = 1;
+    }
+
+  dst = out;
+  *dst++ = '/';
+  in++;
+
+  while (*in == '/')
+    {
+      in++;
+    }
+
+  clamp = out + clamplen;
+
+  while (*in != '\0')
+    {
+      FAR const char *seg = in;
+      size_t seglen;
+
+      while (*in != '\0' && *in != '/')
+        {
+          in++;
+        }
+
+      seglen = (size_t)(in - seg);
+      if (seglen == 0 || (seglen == 1 && seg[0] == '.'))
+        {
+          /* Skip empty or "." segments */
+        }
+      else if (seglen == 2 && seg[0] == '.' && seg[1] == '.')
+        {
+          if (dst > clamp)
+            {
+              dst--;
+              while (dst > out && *(dst - 1) != '/')
+                {
+                  dst--;
+                }
+            }
+        }
+      else
+        {
+          size_t used = (size_t)(dst - out);

Review Comment:
   ditto



##########
fs/vfs/fs_chroot.c:
##########
@@ -0,0 +1,206 @@
+/****************************************************************************
+ * fs/vfs/fs_chroot.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/sched.h>
+
+#include "inode/inode.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: chroot_make_abspath
+ *
+ * Description:
+ *   Build the host absolute path of the directory inode returned by
+ *   inode_find(), including the mount-relative suffix when the jail is
+ *   inside a volume such as tmpfs.
+ *
+ * Input Parameters:
+ *   node    - Inode returned by inode_find()
+ *   relpath - Remaining path inside a mount, or NULL/empty
+ *   out     - Buffer that receives the absolute path
+ *   outlen  - Size of 'out' in bytes
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int chroot_make_abspath(FAR struct inode *node,
+                               FAR const char *relpath,
+                               FAR char *out, size_t outlen)
+{
+  size_t len;
+  int ret;
+
+  ret = inode_getpath(node, out, outlen);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  len = strlen(out);
+  while (len > 1 && out[len - 1] == '/')
+    {
+      out[--len] = '\0';
+    }
+
+  if (relpath != NULL && relpath[0] != '\0')
+    {
+      if (len > 1)
+        {
+          if (len + 1 + strlen(relpath) + 1 > outlen)
+            {
+              return -ENAMETOOLONG;
+            }
+
+          out[len++] = '/';
+          out[len] = '\0';
+        }
+
+      strlcat(out, relpath, outlen);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: chroot
+ *
+ * Description:
+ *   Cause the named directory to become the root directory, that is, the
+ *   starting point for path names beginning with '/'.
+ *
+ * Input Parameters:
+ *   path - Directory to use as the new root
+ *
+ * Returned Value:
+ *   0(OK) on success; -1(ERROR) on failure with errno set appropriately.
+ *
+ ****************************************************************************/
+
+int chroot(FAR const char *path)
+{
+  struct inode_search_s desc;
+  FAR struct tcb_s *rtcb;
+  FAR struct task_group_s *group;
+  FAR char *newroot;
+  char abspath[PATH_MAX];
+  struct stat buf;
+  int errcode;
+  int ret;
+
+  if (path == NULL || path[0] == '\0')
+    {
+      set_errno(ENOENT);
+      return ERROR;
+    }
+
+  rtcb = nxsched_self();
+  DEBUGASSERT(rtcb != NULL && rtcb->group != NULL);
+  group = rtcb->group;
+
+#ifdef CONFIG_SCHED_USER_IDENTITY
+  if (group->tg_euid != 0)
+    {
+      set_errno(EPERM);
+      return ERROR;
+    }
+#endif
+
+  ret = nx_stat(path, &buf, 1);
+  if (ret < 0)
+    {
+      set_errno(-ret);
+      return ERROR;
+    }
+
+  if (!S_ISDIR(buf.st_mode))
+    {
+      set_errno(ENOTDIR);
+      return ERROR;
+    }
+
+  SETUP_SEARCH(&desc, path, false);

Review Comment:
   why need search



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to