Skip to content
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

Add missing system calls for ADC driver subsystem #15001

Merged
merged 3 commits into from
Mar 30, 2019

Conversation

andrewboie
Copy link
Contributor

@andrewboie andrewboie commented Mar 28, 2019

  • Added syscalls for adc_channel_setup() and adc_read()
  • adc_read_async() support will require significant additional refactoring and possibly some kernel-side memory allocations, punting for this PR
  • Increased privileged stack size to fix observed stack overflows

Tested on frdm_k64f and sam_e70_xplained

Partial fix for #14084

Andrew Boie added 3 commits March 28, 2019 15:18
The source data is never modified.

Signed-off-by: Andrew Boie <[email protected]>
The original value of 256 was selected more or less randomly
and special cases keep proliferating. Until we have a formal
method of proving maximum syscall stack depth, set to 1024.

Signed-off-by: Andrew Boie <[email protected]>
Setting callbacks is forbidden from user mode.

Some heavier code changes will be needed to support
adc_read_async(), this patch just exposes the config
and read functions for now.

Test case updated to run partially in user mode.

Signed-off-by: Andrew Boie <[email protected]>
@andrewboie andrewboie added bug The issue is a bug, or the PR is fixing a bug priority: medium Medium impact/importance bug area: ADC Analog-to-Digital Converter (ADC) area: Memory Protection labels Mar 28, 2019
@andrewboie andrewboie requested review from a user and ceolin March 28, 2019 23:57
@codecov-io
Copy link

Codecov Report

Merging #15001 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master   #15001   +/-   ##
=======================================
  Coverage   52.92%   52.92%           
=======================================
  Files         309      309           
  Lines       45268    45268           
  Branches    10451    10451           
=======================================
  Hits        23956    23956           
  Misses      16544    16544           
  Partials     4768     4768

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9e81cbe...14c5054. Read the comment docs.

}

if (dst->options) {
if (z_user_from_copy(options, dst->options,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't copy from src->options ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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)

Copy link
Member

Choose a reason for hiding this comment

The 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:


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);
}

Copy link
Contributor Author

@andrewboie andrewboie Mar 29, 2019

Choose a reason for hiding this comment

The 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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, but this code is not copying user sequence, it is copying sequence that was allocate in this function stack and was not initialized. Well, it seems that I'm not understanding it :/

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is the problem, in copy_sequence you are not using user_sequence=src but sequece=dst

static bool copy_sequence(struct adc_sequence *dst,
			  struct adc_sequence_options *options,
			  struct adc_sequence *src)
{
...

	if (dst->options) { /* dst == sequence that is no uninitialised */
		if (z_user_from_copy(options, dst->options,
				sizeof(struct adc_sequence_options)) != 0) {
			printk("couldn't copy adc_options struct\n");
			return false;
		}
		dst->options = options;
	}
...
}

Copy link
Contributor Author

@andrewboie andrewboie Mar 29, 2019

Choose a reason for hiding this comment

The 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.

Copy link
Member

Choose a reason for hiding this comment

The 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

Copy link
Member

@ceolin ceolin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks ok, only one comment to check.

Copy link
Collaborator

@agross-oss agross-oss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aside from flavio's comment, this looks good.

@andrewboie andrewboie added this to the v1.14.0 milestone Mar 29, 2019
default 512 if COVERAGE_GCOV
default 384 if ARC
default 256
default 1024
Copy link
Member

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

Copy link
Contributor Author

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.

Copy link
Member

@ioannisg ioannisg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine to me (only did a high-level pass)

@nashif nashif merged commit 02be448 into zephyrproject-rtos:master Mar 30, 2019
@anangl
Copy link
Member

anangl commented Apr 1, 2019

I apologize I haven't managed to add this comment before this PR got merged.
Just to ensure it wasn't overlooked. The ADC API allows to provide a callback also to the adc_read function, not only to adc_read_async. I thought this excluded adc_read from being a candidate for a system call. And that's why I haven't provided system calls for this API when reworking it (#7691 (comment)).

@andrewboie andrewboie deleted the adc-syscalls branch April 10, 2019 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: ADC Analog-to-Digital Converter (ADC) area: Memory Protection bug The issue is a bug, or the PR is fixing a bug priority: medium Medium impact/importance bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants