All of lore.kernel.org
 help / color / mirror / Atom feed
* get entire CAN_RAW_FILTER value without knowing its size
@ 2020-12-16  4:33 Phillip Schichtel
  2020-12-16 16:35 ` Oliver Hartkopp
  0 siblings, 1 reply; 8+ messages in thread
From: Phillip Schichtel @ 2020-12-16  4:33 UTC (permalink / raw)
  To: linux-can

Hi everyone!

This is my first post to this mailing list (or any kernel mailing
list), so please tell me if this is the wrong place for this kind of
topic.

I'm developing a Java binding library to SocketCAN using JNI [1], where
I try to provide a reasonably "Java-like" yet efficient and safe API.

Part of this are setters and getters for the SOL_CAN_* socket options,
which is straight forward for all options except CAN_RAW_FILTER, since
it is the only option with a dynamically sized value (struct
can_filter*). Setting the value is simple, since all the information is
available in user space, but when using getsockopt I'm expected to
provide a buffer and a size, but I don't know how many filters there
are without keeping that state in the library or application, risking
it going out of sync with the kernel. Is this correct thus far or am I
missing something? Relevant source on the kernel side is at [2].

On the user space side using getsockopt() I see three ways around this
issue:

1. Track the amount of filters in user space. I feel like this might be
problematic if e.g. sockets get shared between threads and processes.
Other bindings usually take this approach as far as I could tell, if
they support getting filters at all.

2. Allocate a buffer large enough that the filters will most likely all
fit, the optlen will be corrected to the actual size. This is the
approach I currently take (see [3]), but it feels very wrong.

3. Search for the right size by trying increasingly larger buffers
until the buffer is big enough to fit all. This would be kind of an
improvement to 2. for the common case.

Neither of these feel good to me, but maybe that is just me? On the
kernel side ([2]), I could imagine the option taking a void** for
optval and the kernel allocating a new buffer for the caller and
writing its address to the given pointer and the real length to optlen,
kind of like this (without knowing the appropriate functions):


case CAN_RAW_FILTER:
	lock_sock(sk);
	void* filters = NULL;
	if (ro->count > 0) {
		int fsize = ro->count * sizeof(struct can_filter);
		filters = allocate_to_user(fsize);
                if (!optval)
			err = -EFAULT;
		if (copy_to_user(optval, ro->filter, fsize))
			err = -EFAULT;
	} else {
		len = 0;
	}
	release_sock(sk);


	if (!err)
		err = put_user(len, optlen);
	if (!err)
		err = put_user(filters, optval);
	return err;

The setsockopt implementation of the option could also be adapted to
take the same void**.

Alternatively the implementation could always write back the full size
to optlen instead of the "written size" (put_user(fsize, optlen)
instead of put_user(len, optlen) in code). Since the caller knows how
big its buffer is, the size necessary would be the more valuable
information.

Did I completely misunderstand something or is this really a limitation
of the current implementation of this option? And if the latter is
true, are we in the position to change anything about this without
breaking user space?

I also haven't really looked into how other protocols handle
dynamically sized option values or if that is even a thing else where.

Either way, any feedback on this is very much appreciated!

~ Phillip Schichtel

[1]: https://github.com/pschichtel/JavaCAN
[2]:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/can/raw.c?h=v5.10#n663

[3]:
https://github.com/pschichtel/JavaCAN/blob/ab64fb416996978fc154f84c204bf25273ab1776/core/src/main/c/javacan_socketcan.c#L176-L182


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

end of thread, other threads:[~2020-12-18  7:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-16  4:33 get entire CAN_RAW_FILTER value without knowing its size Phillip Schichtel
2020-12-16 16:35 ` Oliver Hartkopp
2020-12-16 17:55   ` Phillip Schichtel
2020-12-16 18:31     ` Oliver Hartkopp
2020-12-17 12:19       ` Oliver Hartkopp
2020-12-17 16:33         ` Phillip Schichtel
2020-12-17 16:42           ` Oliver Hartkopp
2020-12-18  7:50           ` Marc Kleine-Budde

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.