Bug 248223

Summary: Linuxulator: pread behavior differences
Product: Base System Reporter: Alex S <iwtcex>
Component: kernAssignee: Edward Tomasz Napierala <trasz>
Status: In Progress ---    
Severity: Affects Only Me CC: cem, emaste, trasz
Priority: ---    
Version: 12.1-RELEASE   
Hardware: amd64   
OS: Any   
Bug Depends on:    
Bug Blocks: 247219    

Description Alex S 2020-07-23 19:05:50 UTC
% cat pread.c
#define _GNU_SOURCE

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>

void pread_v(int fd, void* buf, size_t nbytes, off64_t offset) {
  printf("pread(_, _, 0x%lx, _) -> ", nbytes);
  int ret = pread(fd, buf, nbytes, offset);
  if (ret != -1) {
    printf("0x%x\n", ret);
  } else {
    printf("%s\n", strerror(errno));
  }
}

int main() {

  int mem = open("/proc/self/mem", O_RDONLY);
  assert(mem != -1);

  char buf[0x4000];

  pread_v(mem, buf, 0x1000, 0); // should be EIO
  printf("---\n");

  void* p1 = mmap(NULL,        0x2000, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,             -1, 0);
  void* p2 = mmap(p1 + 0x1000, 0x1000, PROT_NONE,              MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);

  assert(p1 != MAP_FAILED);
  assert(p2 == p1 + 0x1000);

  assert(munmap(p2, 0x1000) == 0);

  for (int n = sizeof(buf); n >= 0x1000; n /= 2) {
    pread_v(mem, buf, n, (off64_t)p1); // should return 0x1000
  }

  return 0;
}
% /compat/linux/bin/gcc -std=c99 -Wall pread.c -o pread
% ./pread
pread(_, _, 0x1000, _) -> Bad address
---
pread(_, _, 0x4000, _) -> Bad address
pread(_, _, 0x2000, _) -> Bad address
pread(_, _, 0x1000, _) -> 0x1000

On the other hand, Linux (Xubuntu 18.04.3) prints Input/Output errors and 0x1000, 0x1000, 0x1000 there.
Comment 1 Alex S 2020-07-23 19:08:01 UTC
(This may or may not be relevant to the Valve Anti-Cheat functionality in Steam.)
Comment 2 Alex S 2020-07-23 19:08:57 UTC
s/errors/error/
Comment 3 Edward Tomasz Napierala freebsd_committer 2020-10-16 16:04:58 UTC
https://reviews.freebsd.org/D26816
Comment 4 commit-hook freebsd_committer 2020-10-20 17:25:27 UTC
A commit references this bug:

Author: trasz
Date: Tue Oct 20 17:24:30 UTC 2020
New revision: 366900
URL: https://svnweb.freebsd.org/changeset/base/366900

Log:
  Fix linprocfs(4) /proc/self/mem semantics to more closely match Linux.
  Steam's Anti-Cheat might depend on it.

  PR:		248223
  Analyzed by:	Alex S <iwtcex@gmail.com>
  Reviewed by:	kib
  MFC after:	2 weeks
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D26816

Changes:
  head/sys/compat/linprocfs/linprocfs.c