-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Add missing system calls for ADC driver subsystem #15001
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| /* | ||
| * Copyright (c) 2019 Intel Corporation | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| #include <adc.h> | ||
| #include <syscall_handler.h> | ||
| #include <kernel.h> | ||
|
|
||
| Z_SYSCALL_HANDLER(adc_channel_setup, dev, user_channel_cfg) | ||
| { | ||
| struct adc_channel_cfg channel_cfg; | ||
|
|
||
| Z_OOPS(Z_SYSCALL_DRIVER_ADC(dev, channel_setup)); | ||
| Z_OOPS(z_user_from_copy(&channel_cfg, | ||
| (struct adc_channel_cfg *)user_channel_cfg, | ||
| sizeof(struct adc_channel_cfg))); | ||
|
|
||
| return z_impl_adc_channel_setup((struct device *)dev, &channel_cfg); | ||
| } | ||
|
|
||
| static bool copy_sequence(struct adc_sequence *dst, | ||
| struct adc_sequence_options *options, | ||
| struct adc_sequence *src) | ||
| { | ||
| if (z_user_from_copy(dst, src, sizeof(struct adc_sequence)) != 0) { | ||
| printk("couldn't copy adc_sequence struct\n"); | ||
| return false; | ||
| } | ||
|
|
||
| if (dst->options) { | ||
| if (z_user_from_copy(options, dst->options, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't copy from
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. at this point in the code, src and dst have the same contents since we just previously copied src (a pointer into user memory) into dst (a pointer on the supervisor mode call stack)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is not making sense to me though. Why do you need this check and copy then ? dst is an uninitialised variable:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you need to copy user_sequence (lives somehere in user memory) into kernel memory (sequence) in order to prevent TOCTOU issues. notice I am not passing user_sequence to the syscall implementation.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, but this code is not copying user sequence, it is copying
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you're not reading the code right, you have it backwards. user_sequence=src sequence=dst
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that is the problem, in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please post the whole function. You will see that immediately before the check to dst->options, all of src got copied into dst. It is initialized. dst->options points to a different memory buffer provided by the user, we copy it and then update dst->options.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I missed that first copy, damn it. My bad, sorry for all noise |
||
| sizeof(struct adc_sequence_options)) != 0) { | ||
| printk("couldn't copy adc_options struct\n"); | ||
| return false; | ||
| } | ||
| dst->options = options; | ||
| } | ||
|
|
||
| if (Z_SYSCALL_MEMORY_WRITE(dst->buffer, dst->buffer_size) != 0) { | ||
| printk("no access to buffer memory\n"); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
|
|
||
| Z_SYSCALL_HANDLER(adc_read, dev, user_sequence) | ||
| { | ||
| struct adc_sequence sequence; | ||
| struct adc_sequence_options options; | ||
|
|
||
| Z_OOPS(Z_SYSCALL_DRIVER_ADC(dev, read)); | ||
| Z_OOPS(Z_SYSCALL_VERIFY_MSG(copy_sequence(&sequence, &options, | ||
| (struct adc_sequence *)user_sequence), | ||
| "invalid ADC sequence")); | ||
| if (sequence.options != NULL) { | ||
| Z_OOPS(Z_SYSCALL_VERIFY_MSG(sequence.options->callback == NULL, | ||
| "ADC sequence callbacks forbidden from user mode")); | ||
| } | ||
|
|
||
| return z_impl_adc_read((struct device *)dev, &sequence); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with the rationale, here, but, I see that the priv stack starts getting too big
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure what you mean by too big
The actual minimum value for this, that satisfies maximum depth for all kernel/driver syscalls is unknown at this time.