Esempio n. 1
0
/**
 * strlen_user: - Get the size of a user string INCLUDING final NUL.
 * @str: The string to measure.
 *
 * Context: User context only.  This function may sleep.
 *
 * Get the size of a NUL-terminated string in user space.
 *
 * Returns the size of the string INCLUDING the terminating NUL.
 * On exception, returns 0.
 *
 * If there is a limit on the length of a valid string, you may wish to
 * consider using strnlen_user() instead.
 */
long strlen_user(const char __user *str)
{
	unsigned long max_addr, src_addr;

	max_addr = user_addr_max();
	src_addr = (unsigned long)str;
	if (likely(src_addr < max_addr)) {
		unsigned long max = max_addr - src_addr;
		return do_strnlen_user(str, ~0ul, max);
	}
	return 0;
}
Esempio n. 2
0
/**
 * strncpy_from_user: - Copy a NUL terminated string from userspace.
 * @dst:   Destination address, in kernel space.  This buffer must be at
 *         least @count bytes long.
 * @src:   Source address, in user space.
 * @count: Maximum number of bytes to copy, including the trailing NUL.
 *
 * Copies a NUL-terminated string from userspace to kernel space.
 *
 * On success, returns the length of the string (not including the trailing
 * NUL).
 *
 * If access to userspace fails, returns -EFAULT (some data may have been
 * copied).
 *
 * If @count is smaller than the length of the string, copies @count bytes
 * and returns @count.
 */
long strncpy_from_user(char *dst, const char __user *src, long count)
{
	unsigned long max_addr, src_addr;

	if (unlikely(count <= 0))
		return 0;

	max_addr = user_addr_max();
	src_addr = (unsigned long)src;
	if (likely(src_addr < max_addr)) {
		unsigned long max = max_addr - src_addr;
		return do_strncpy_from_user(dst, src, count, max);
	}
	return -EFAULT;
}
Esempio n. 3
0
/**
 * strnlen_user: - Get the size of a user string INCLUDING final NUL.
 * @str: The string to measure.
 * @count: Maximum count (including NUL character)
 *
 * Context: User context only.  This function may sleep.
 *
 * Get the size of a NUL-terminated string in user space.
 *
 * Returns the size of the string INCLUDING the terminating NUL.
 * If the string is too long, returns 'count+1'.
 * On exception (or invalid count), returns 0.
 */
long strnlen_user(const char __user *str, long count)
{
	unsigned long max_addr, src_addr;

	if (unlikely(count <= 0))
		return 0;

	max_addr = user_addr_max();
	src_addr = (unsigned long)str;
	if (likely(src_addr < max_addr)) {
		unsigned long max = max_addr - src_addr;
		return do_strnlen_user(str, count, max);
	}
	return 0;
}
Esempio n. 4
0
static int
lookup_bad_addr(const int type, const unsigned long addr, const size_t size)
{
  /* Is this a valid memory access?
   * 
   * Note we're using access_ok() here. This is only supposed to be
   * called when we're in task context. Occasionally lookup_bad_addr()
   * gets called when not in task context. If in_task() exists, only
   * call access_ok() when we're in task context (otherwise we'll get
   * a kernel warning). If we aren't in task context, we'll just do a
   * range check.
   */
#if !defined(in_task)
  if (size == 0 || ULONG_MAX - addr < size - 1
      || !access_ok(type, (void *)addr, size))
    return 1;
#else
  if (size == 0 || ULONG_MAX - addr < size - 1
      || (in_task() && !access_ok(type, (void *)addr, size))
      || (!in_task()
#if defined(user_addr_max)
	  && ((user_addr_max() - size) < addr)
#endif
	      ))
    return 1;
#endif

#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \
    ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)
  /* Unprivileged users must not access memory while the context
     does not refer to their own process.  */
  if (! is_myproc ())
    return 1;
  /* Unprivileged users must not access kernel space memory.  */
  if (addr + size > TASK_SIZE)
    return 1;
#endif

  return 0;
}