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

release: use locking around lazy intialized state #6306

Merged
merged 11 commits into from
Dec 20, 2018

Conversation

bboozzoo
Copy link
Contributor

Some state data in the release package, namely AppArmor level/summary &
kernel/parser features as well as Seccomp feature set, is only initialized when
needed. Since there is a chance, this information could be accessed in
concurrently, we need to add some locking around the code that mutates the data.

Some state data in the release package, namely AppArmor level/summary &
kernel/parser features as well as Seccomp feature set, is only initialized when
needed. Since there is a chance, this information could be accessed in
concurrently, we need to add some locking around the code that mutates the data.

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
@bboozzoo bboozzoo added the Simple 😃 A small PR which can be reviewed quickly label Dec 13, 2018
@bboozzoo bboozzoo requested a review from zyga December 13, 2018 12:28
zyga
zyga previously approved these changes Dec 13, 2018
Copy link
Contributor

@zyga zyga left a comment

Choose a reason for hiding this comment

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

LGTM but let's please just use one mutex for both AppArmor variables.

@pedronis
Copy link
Collaborator

using sync.Once would be more idiomatic

Refactor the AppArmor and Seccomp handling code to use sync.Once, in hope for
making the code more idiomatic. Drop or update the necessary tests.

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
@bboozzoo
Copy link
Contributor Author

@pedronis pushed the change to use sync.Once.

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

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

some questions/comments

)

func assessAppArmorOnce() {
appArmorAssessOnce.Do(assessAppArmor)
Copy link
Collaborator

Choose a reason for hiding this comment

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

were the actual functions like assesAppArmor etc tested?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@zyga zyga dismissed their stale review December 14, 2018 23:04

I need to re-read the new code

@codecov-io
Copy link

codecov-io commented Dec 15, 2018

Codecov Report

Merging #6306 into master will increase coverage by 0.02%.
The diff coverage is 95.12%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #6306      +/-   ##
==========================================
+ Coverage   78.95%   78.98%   +0.02%     
==========================================
  Files         561      561              
  Lines       43650    43664      +14     
==========================================
+ Hits        34463    34486      +23     
+ Misses       6387     6378       -9     
  Partials     2800     2800
Impacted Files Coverage Δ
release/seccomp.go 92.59% <90%> (+32.59%) ⬆️
release/apparmor.go 95.71% <96.77%> (+0.35%) ⬆️
overlord/hookstate/hookmgr.go 73.55% <0%> (-0.97%) ⬇️
image/image.go 72.98% <0%> (-0.08%) ⬇️
wrappers/core18.go 49.47% <0%> (ø) ⬆️
overlord/ifacestate/handlers.go 62.7% <0%> (+0.51%) ⬆️
cmd/snap/cmd_run.go 62.52% <0%> (+1.71%) ⬆️

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 f3c9121...d91930d. Read the comment docs.

// appArmorProbeParserOnce sync.Once
// appArmorProbeKernelOnce sync.Once
// appArmorAssessOnce sync.Once
type appArmorOnceBattery struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not super fond of the name.

if appArmorLevel == UnknownAppArmor {
assessAppArmor()
}
appArmorAssess()
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have a test that checks if the assessment is cached and actually done once? Since this extra if goes away, it would be good to have a test, in case the implementation based on sync.Once gets replaced in the future with new Go.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I looked into this, in the end I reorganized things quite a bit, mostly because the Mock* functions below are complicated/long but didn't help fully with testing this. I'm pushing the new code now, with it commenting the Once.Do bits always make some test fail.

…g them swapping full structures, add various tests increasing coverage and proving that the once-only logic is in place
appArmorKernelFeatures, appArmorKernelError = probeAppArmorKernelFeatures()
}
return appArmorKernelFeatures, appArmorKernelError
return appArmorAssessment.KernelFeatures()
Copy link
Contributor

Choose a reason for hiding this comment

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

Mostly curiuous - is there a reason we use slightly different pattern here and above? I mean explicit call to assess(), rather than having Level() and Summary() methods that to sync.Once internally?

Copy link
Collaborator

Choose a reason for hiding this comment

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

These ones are used both internally and externally and also participate in the interface. Summary and Level are just exposed externally so having another layer of methods didn't seem interesting just for the symmetry.

appArmorLevel = NoAppArmor
appArmorSummary = "apparmor not enabled"
return
return NoAppArmor, "apparmor not enabled"
Copy link
Contributor

Choose a reason for hiding this comment

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

This is nice, after writing this I was thinking about changing the code around to avoid the risk of forgetting to return. This makes the problem moot.

appArmorLevel = NoAppArmor
appArmorSummary = "apparmor not enabled"
return
return NoAppArmor, "apparmor not enabled"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

What about other errors? I think with the change to the func AppArmorKernelFeatures() ([]string, error) method we are no longer returning actual appArmorKernelError from AppArmorKernelFeatures, no?

Copy link
Collaborator

Choose a reason for hiding this comment

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

appArmorKernelError doesn't exist anymore as a global, it's stored in the kernelError field of the impl of appArmorProber, and returned in their KernelFeatures methods and then out of AppArmorKernelFeatures

Copy link
Contributor

@stolowski stolowski left a comment

Choose a reason for hiding this comment

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

LGTM. But I don't think "Simple" label is true anymore ;)

@pedronis pedronis removed the Simple 😃 A small PR which can be reviewed quickly label Dec 20, 2018
Copy link
Contributor

@chipaca chipaca left a comment

Choose a reason for hiding this comment

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

Nice. Thank you!

Copy link
Contributor Author

@bboozzoo bboozzoo left a comment

Choose a reason for hiding this comment

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

@pedronis thanks for the cleanup!

@pedronis pedronis merged commit 318896a into canonical:master Dec 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants