mirror of
https://github.com/apache/nuttx.git
synced 2026-10-08 14:55:18 +00:00
ttyname_r() passed the caller buffer straight to fcntl(F_GETPATH) whenever buflen >= TTY_NAME_MAX, but every FIOC_FILEPATH handler writes the path bounded by PATH_MAX and ignores the caller buffer size. A tty registered under a nested /dev path, or reached through rpmsgfs, has a path longer than TTY_NAME_MAX and overwrote the caller buffer, silently corrupting memory behind a zero return code. The small-buffer branch had the same defect against its own stack local char name[TTY_NAME_MAX]. Gate the direct write on PATH_MAX instead and stage the path through a PATH_MAX path buffer obtained via lib_get_tempbuffer(), returning ERANGE when it does not fit. Verified on sim:nsh with a test driver registered at an 85-character tty path: pre-fix, ttyname_r(buf, TTY_NAME_MAX) returned 0 and smashed the canaries behind the buffer, and the small-buffer branch panicked; post-fix both cases return ERANGE with the canaries intact. Assisted-by: Claude Code (glm-5.3) <claude@anthropic.com> Signed-off-by: Junbo Zheng <zhengjunbo1@xiaomi.com>
100 lines
3.3 KiB
C
100 lines
3.3 KiB
C
/****************************************************************************
|
|
* libs/libc/termios/lib_ttynamer.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 <errno.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include <nuttx/lib/lib.h>
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: ttyname_r
|
|
*
|
|
* Description:
|
|
* The ttyname_r() function shall store the null-terminated pathname of
|
|
* the terminal associated with the file descriptor fildes in the
|
|
* character array referenced by name. The array is namesize characters
|
|
* long and should have space for the name and the terminating null
|
|
* character. The maximum length of the terminal name shall be
|
|
* {TTY_NAME_MAX}.
|
|
*
|
|
* Input Parameters:
|
|
* fd - The 'fd' argument is an open file descriptor associated with
|
|
* a terminal.
|
|
* buf - Caller provided buffer to hold tty name.
|
|
* buflen - The size of the caller-provided buffer.
|
|
*
|
|
* Returned Value:
|
|
* If successful, the ttyname_r() function shall return zero.
|
|
* Otherwise, an error number shall be returned to indicate the error.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int ttyname_r(int fd, FAR char *buf, size_t buflen)
|
|
{
|
|
if (!isatty(fd))
|
|
{
|
|
return ENOTTY;
|
|
}
|
|
|
|
/* The F_GETPATH handler copies the file path into the caller buffer
|
|
* bounded by PATH_MAX, not by any tty-specific limit, so the path must
|
|
* always land in a PATH_MAX-sized buffer first. Only a caller buffer
|
|
* of that size can receive it directly.
|
|
*/
|
|
|
|
if (buflen >= PATH_MAX)
|
|
{
|
|
return fcntl(fd, F_GETPATH, buf) < 0 ? get_errno() : 0;
|
|
}
|
|
else
|
|
{
|
|
FAR char *path = lib_get_tempbuffer(PATH_MAX);
|
|
int ret;
|
|
|
|
if (fcntl(fd, F_GETPATH, path) < 0)
|
|
{
|
|
ret = get_errno();
|
|
}
|
|
else if (strlen(path) >= buflen)
|
|
{
|
|
ret = ERANGE;
|
|
}
|
|
else
|
|
{
|
|
strlcpy(buf, path, buflen);
|
|
ret = OK;
|
|
}
|
|
|
|
lib_put_tempbuffer(path);
|
|
return ret;
|
|
}
|
|
}
|