Re: [PATCH v7 4/7] can: canxl: introduce CAN XL data structure

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun. 31 Jul. 2022 at 06:05, Oliver Hartkopp <socketcan@xxxxxxxxxxxx> wrote:
> On 30.07.22 15:16, Vincent Mailhol wrote:
> > On Sat. 30 juil. 2022 at 21:06, Oliver Hartkopp <socketcan@xxxxxxxxxxxx> wrote:
>
> >>> Existing applications are exempted from this risk: the
> >>> CAN_RAW_XL_FRAMES socket option will prevent the collision from
> >>> happening. To summarise, the collision will only occur if below
> >>> criteria are met:
> >>>
> >>>     * The user allocates a can_frame without zeroing it (typical use
> >>> cases are stack declaration or malloc()).
> >>>     * The user activates the CAN_RAW_XL_FRAMES socket option.
> >>>     * Garbage value results in can_frame::__pad & CANXL_XLF being set.
> >>>
> >>> So if going in that direction, we would have to update the
> >>> documentation (header files and kernel doc) to point at this pitfall
> >>> and specify that can_frame::__pad shall always be zeroed for mix
> >>> usages.
> >>
> >> But you would add this recommendation to a *very late point* - namely
> >> after 14 years of SocketCAN in the mainline kernel.
> >>
> >> If you think about the rule "never break user space" I wonder if the
> >> risk turns out to be higher when people enable CAN_RAW_XL_FRAMES ("as
> >> seen on Stackoverflow") and not read the kernel doc recommendations to
> >> review/update their existing code.
> >
> > In which aspect does this break the user space? It doesn't.
>
> It does in the way that you need to zero-initialize structures now.
>
> > Enabling CAN_RAW_XL_FRAMES marks a clear transition between the 14
> > years old Classical CAN API and the new use case of mixed CAN(-FD) and
> > CAN XL frames.
>
> You are seriously telling me that CAN_RAW_XL_FRAMES is a clear
> transition and people will automatically review and rework their former
> CAN/CANFD code to zero-initialize padding bytes?
>
> There is a much higher risk that this does not happen than telling
> people to check for CANXL_XLF first after reading from the socket!
>
> > For the issue to occur, developers have to incorrectly modify their
> > application, I do not call this a break in user space if only the
> > yet-to-be-created programs are impacted.
>
> I don't know about your thresholds but I call this a break in user
> space. Yet-to-be-created programs will likely copy old code.
>
> > The argument that people do not read the kernel doc apply to both
> > cases: some people will not initialise variables, some people will not
> > do the "if" checks in the right order.
>
> To make it simple: The difference between CAN XL and (old) CAN/CANFD
> handling is CANXL_XLF.
>
> I'm really tired about your constructed case that people would be too
> dumb to check for CANXL_XLF first.
>
> This CANFD_FDF check is a new optional(!) possibility, which we do not
> need to promote. This could become a power user trick for people that
> are obviously "smart enough" to put if-statements in the right order.
>
> The correct and safe check that should be documented and suggested looks
> like this:
>
> if (can.xl.flags & CANXL_XLF)
>       /* Handle CAN XL frame */
> else if (nbytes == CANFD_MTU)
>       /* Handle CAN FD frame */
> else if (nbytes == CAN_MTU) /* paranoid */
>       /* Handle Classic CAN frame */
> else
>       /* error */

After a good night of sleep, I found a use case which destroys my idea:

int main()
{
    static union can can;

    can.xl.flags = CANXL_XLF;
    /* set other fields, open socket... */
    write(s, &can.xl, CANXL_HD_SIZE + can.xl.len);

    can.cc.len = 8;
    /* set other field but leave can.cc._pad untouched */
    write(s, &can.cc, sizeof(can.cc));

    /* ... */
}

Here, we have a static declaration so the frame is guaranteed to be
zero initialized. The user then sends a CAN XL frame (and thus sets
the CANXL_XLF flag). Then the user sends a Classic CAN frame. However,
can.cc._pad still contains the CANXL_XLF flag set. I stay in my
position that asking to zero initialize variables for mix usage is
acceptable. But requiring to reset the can.cc._pad to zero in the
middle of the run time is too much.
This is a very bad foot gun. So let me withdraw my idea. Using the
0x80 flag on the can(fd)_frame.len is the best.


Yours sincerely,
Vincent Mailhol



[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux