All of lore.kernel.org
 help / color / mirror / Atom feed
* FOP_UNSIGNED_OFFSET abuse
@ 2026-05-21  7:09 Dan Carpenter
  2026-05-21  8:36 ` Arnd Bergmann
  0 siblings, 1 reply; 2+ messages in thread
From: Dan Carpenter @ 2026-05-21  7:09 UTC (permalink / raw)
  To: linux-fsdevel, dri-devel, Christian Brauner; +Cc: Arnd Bergmann

Is there a point to FOP_UNSIGNED_OFFSET now that everyone is on 64bit?
I thought the flag was for back in the day where we it was a huge deal
to access 4GB instead of 2GB.

It's mostly used in DRM.  drm_open_helper() forces you to set the flag
but drm_read() ignores the offset so I don't understand the point of
this.

regards,
dan carpenter

$ git grep FOP_UNSIGNED_OFFSET
drivers/accel/amdxdna/amdxdna_pci_drv.c:        .fop_flags      = FOP_UNSIGNED_OFFSET,
drivers/char/adi.c:     .fop_flags      = FOP_UNSIGNED_OFFSET,
drivers/char/mem.c:     .fop_flags      = FOP_UNSIGNED_OFFSET,
drivers/gpu/drm/adp/adp_drv.c:  .fop_flags      = FOP_UNSIGNED_OFFSET,
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c:        .fop_flags = FOP_UNSIGNED_OFFSET,
drivers/gpu/drm/drm_file.c:     if (WARN_ON_ONCE(!(filp->f_op->fop_flags & FOP_UNSIGNED_OFFSET)))
drivers/gpu/drm/gma500/psb_drv.c:       .fop_flags = FOP_UNSIGNED_OFFSET,
drivers/gpu/drm/i915/i915_driver.c:     .fop_flags = FOP_UNSIGNED_OFFSET,
drivers/gpu/drm/nouveau/nouveau_drm.c:  .fop_flags = FOP_UNSIGNED_OFFSET,
drivers/gpu/drm/panthor/panthor_drv.c:  .fop_flags = FOP_UNSIGNED_OFFSET,
drivers/gpu/drm/radeon/radeon_drv.c:    .fop_flags = FOP_UNSIGNED_OFFSET,
drivers/gpu/drm/tegra/drm.c:    .fop_flags = FOP_UNSIGNED_OFFSET,
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c:    .fop_flags = FOP_UNSIGNED_OFFSET,
drivers/gpu/drm/xe/xe_device.c: .fop_flags = FOP_UNSIGNED_OFFSET,
fs/proc/base.c: if (WARN_ON_ONCE(!(file->f_op->fop_flags & FOP_UNSIGNED_OFFSET)))
fs/proc/base.c: .fop_flags      = FOP_UNSIGNED_OFFSET,
fs/read_write.c:        return file->f_op->fop_flags & FOP_UNSIGNED_OFFSET;
include/drm/drm_accel.h:        .fop_flags      = FOP_UNSIGNED_OFFSET
include/drm/drm_gem.h:  .fop_flags      = FOP_UNSIGNED_OFFSET
include/drm/drm_gem_dma_helper.h:               .fop_flags = FOP_UNSIGNED_OFFSET, \
include/linux/fs.h:#define FOP_UNSIGNED_OFFSET  ((__force fop_flags_t)(1 << 5))
mm/mmap.c:      if (file->f_op->fop_flags & FOP_UNSIGNED_OFFSET)
rust/bindings/bindings_helper.h:const fop_flags_t RUST_CONST_HELPER_FOP_UNSIGNED_OFFSET = FOP_UNSIGNED_OFFSET;
rust/kernel/drm/gem/mod.rs:    fops.fop_flags = bindings::FOP_UNSIGNED_OFFSET;



^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: FOP_UNSIGNED_OFFSET abuse
  2026-05-21  7:09 FOP_UNSIGNED_OFFSET abuse Dan Carpenter
@ 2026-05-21  8:36 ` Arnd Bergmann
  0 siblings, 0 replies; 2+ messages in thread
From: Arnd Bergmann @ 2026-05-21  8:36 UTC (permalink / raw)
  To: Dan Carpenter, linux-fsdevel, dri-devel, Christian Brauner

On Thu, May 21, 2026, at 09:09, Dan Carpenter wrote:
> Is there a point to FOP_UNSIGNED_OFFSET now that everyone is on 64bit?
> I thought the flag was for back in the day where we it was a huge deal
> to access 4GB instead of 2GB.
>
> It's mostly used in DRM.  drm_open_helper() forces you to set the flag
> but drm_read() ignores the offset so I don't understand the point of
> this.

As far as I understand it, this is needed specifically for
character devices with an mmap() file operation that encodes
information in the high offset bits, see be83bbf80682 ("mmap:
introduce sane default mmap limits").

For /dev/kmem, this is is needed to access the actual kernel
memory on architectures that map it to negative addresses,
and this one actually does llseek/read/write up to U64_MAX,
which would be useful on 32-bit compat tasks reading 64-bit
kernel memory, and we could probably just not do that.

For the mmap() interface, I see that things are a bit messy
in multiple ways:

- DRM drivers on 32-bit kernels need this to mmap() GEM
  buffer objects that have a file offset just above
  ULONG_MAX, which is the limit in file_mmap_size_max()
  for character devices. 
  As you pointed out, llseek/read/write does not have this
  limit.

- mmap2() can never map up to ULLONG_MAX even with the flag,
  but is in practice limited to 2^44 (ULONG_MAX << 12)
  when FOP_UNSIGNED_OFFSET is set.

- compat_mmap() checks against the 64-bit MAX_LFS_FILESIZE
  and ULONG_MAX in file_mmap_ok(), so it's actually able
  to map beyond these limits. I suppose this is not a
  bug itself, but is unexpected.

- MAX_LFS_FILESIZE itself is defined as
  "((loff_t)ULONG_MAX << PAGE_SHIFT)" on 32-bit systems,
  but mmap2() actually uses a fixed 12 bit shift
  rather than PAGE_SHIFT on most architectures with
  a compile-time page size choice.

       Arnd

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-05-21  8:37 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-21  7:09 FOP_UNSIGNED_OFFSET abuse Dan Carpenter
2026-05-21  8:36 ` Arnd Bergmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.