Merge lp:~thomas-voss/trust-store/fix-1518883 into lp:trust-store

Proposed by Thomas Voß
Status: Superseded
Proposed branch: lp:~thomas-voss/trust-store/fix-1518883
Merge into: lp:trust-store
Diff against target: 326 lines (+250/-1)
6 files modified
src/CMakeLists.txt (+3/-0)
src/core/trust/daemon.cpp (+6/-1)
src/core/trust/privilege_escalation_prevention_agent.cpp (+52/-0)
src/core/trust/privilege_escalation_prevention_agent.h (+63/-0)
tests/CMakeLists.txt (+20/-0)
tests/privilege_escalation_prevention_agent_test.cpp (+106/-0)
To merge this branch: bzr merge lp:~thomas-voss/trust-store/fix-1518883
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Ubuntu Phablet Team Pending
Review via email: mp+278292@code.launchpad.net

This proposal has been superseded by a proposal from 2015-11-24.

Commit message

Introduce a trust::PrivilegeEscalationPreventionAgent, filtering out invalid requests. Fixes lp:#1518883.

Description of the change

Introduce a trust::PrivilegeEscalationPreventionAgent, filtering out invalid requests. Fixes lp:#1518883.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
139. By Thomas Voß

Remove obsolote check in mir::Agent.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/CMakeLists.txt'
2--- src/CMakeLists.txt 2015-08-31 13:16:20 +0000
3+++ src/CMakeLists.txt 2015-11-23 09:47:36 +0000
4@@ -43,6 +43,9 @@
5 core/trust/app_id_formatting_trust_agent.h
6 core/trust/app_id_formatting_trust_agent.cpp
7
8+ # An agent implementation preventing privilege escalation attacks.
9+ core/trust/privilege_escalation_prevention_agent.cpp
10+
11 # An agent-implementation that allows for selectively whitelisting app ids
12 core/trust/white_listing_agent.cpp
13 # An agent-implementation using a store instance to cache user replies.
14
15=== modified file 'src/core/trust/daemon.cpp'
16--- src/core/trust/daemon.cpp 2015-08-31 14:00:41 +0000
17+++ src/core/trust/daemon.cpp 2015-11-23 09:47:36 +0000
18@@ -22,6 +22,7 @@
19 #include <core/trust/cached_agent.h>
20 #include <core/trust/expose.h>
21 #include <core/trust/i18n.h>
22+#include <core/trust/privilege_escalation_prevention_agent.h>
23 #include <core/trust/store.h>
24 #include <core/trust/white_listing_agent.h>
25
26@@ -375,6 +376,10 @@
27 }, cached_agent);
28
29 auto formatting_agent = std::make_shared<core::trust::AppIdFormattingTrustAgent>(whitelisting_agent);
30+
31+ auto privilege_escalation_prevention_agent = std::make_shared<core::trust::PrivilegeEscalationPreventionAgent>(
32+ core::trust::PrivilegeEscalationPreventionAgent::default_user_id_functor(),
33+ formatting_agent);
34
35 auto remote_agent = remote_agent_factory(service_name, formatting_agent, dict);
36
37@@ -382,7 +387,7 @@
38 {
39 service_name,
40 bus_from_name(vm[Parameters::StoreBus::name].as<std::string>()),
41- {local_store, formatting_agent},
42+ {local_store, privilege_escalation_prevention_agent},
43 {remote_agent}
44 };
45 }
46
47=== added file 'src/core/trust/privilege_escalation_prevention_agent.cpp'
48--- src/core/trust/privilege_escalation_prevention_agent.cpp 1970-01-01 00:00:00 +0000
49+++ src/core/trust/privilege_escalation_prevention_agent.cpp 2015-11-23 09:47:36 +0000
50@@ -0,0 +1,52 @@
51+/*
52+ * Copyright © 2015 Canonical Ltd.
53+ *
54+ * This program is free software: you can redistribute it and/or modify it
55+ * under the terms of the GNU Lesser General Public License version 3,
56+ * as published by the Free Software Foundation.
57+ *
58+ * This program is distributed in the hope that it will be useful,
59+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
60+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61+ * GNU Lesser General Public License for more details.
62+ *
63+ * You should have received a copy of the GNU Lesser General Public License
64+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
65+ *
66+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
67+ */
68+
69+#include <core/trust/privilege_escalation_prevention_agent.h>
70+
71+#include <unistd.h>
72+#include <sys/types.h>
73+
74+core::trust::PrivilegeEscalationPreventionAgent::Error::Error() : std::runtime_error{"Potential privilege escalation attack detected."}
75+{
76+}
77+
78+core::trust::PrivilegeEscalationPreventionAgent::UserIdFunctor core::trust::PrivilegeEscalationPreventionAgent::default_user_id_functor()
79+{
80+ return []()
81+ {
82+ return core::trust::Uid{::getuid()};
83+ };
84+}
85+
86+core::trust::PrivilegeEscalationPreventionAgent::PrivilegeEscalationPreventionAgent(
87+ const UserIdFunctor& uid_functor,
88+ const std::shared_ptr<core::trust::Agent>& impl)
89+ : uid_functor{uid_functor},
90+ impl{impl}
91+{
92+ if (not impl) throw std::runtime_error
93+ {
94+ "Missing agent implementation."
95+ };
96+}
97+
98+core::trust::Request::Answer core::trust::PrivilegeEscalationPreventionAgent::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters)
99+{
100+ if (uid_functor() != parameters.application.uid) throw Error{};
101+ return impl->authenticate_request_with_parameters(parameters);
102+}
103
104=== added file 'src/core/trust/privilege_escalation_prevention_agent.h'
105--- src/core/trust/privilege_escalation_prevention_agent.h 1970-01-01 00:00:00 +0000
106+++ src/core/trust/privilege_escalation_prevention_agent.h 2015-11-23 09:47:36 +0000
107@@ -0,0 +1,63 @@
108+/*
109+ * Copyright © 2015 Canonical Ltd.
110+ *
111+ * This program is free software: you can redistribute it and/or modify it
112+ * under the terms of the GNU Lesser General Public License version 3,
113+ * as published by the Free Software Foundation.
114+ *
115+ * This program is distributed in the hope that it will be useful,
116+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
117+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
118+ * GNU Lesser General Public License for more details.
119+ *
120+ * You should have received a copy of the GNU Lesser General Public License
121+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
122+ *
123+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
124+ */
125+
126+#ifndef CORE_TRUST_PRIVILEGE_ESCALATION_PREVENTION_AGENT_H_
127+#define CORE_TRUST_PRIVILEGE_ESCALATION_PREVENTION_AGENT_H_
128+
129+#include <core/trust/agent.h>
130+
131+#include <stdexcept>
132+
133+namespace core
134+{
135+namespace trust
136+{
137+// A PrivilegeEscalationPreventionAgent ensures that requests originating from an application
138+// running under a different user than the current one are rejected immediately, thereby preventing
139+// from privilege escalation issues.
140+class CORE_TRUST_DLL_PUBLIC PrivilegeEscalationPreventionAgent : public core::trust::Agent
141+{
142+public:
143+ // An Error is thrown if a potential privilege escalation attack has been detected.
144+ struct Error : public std::runtime_error
145+ {
146+ // Error creates an instance, providing details about the escalation issue.
147+ Error();
148+ };
149+
150+ // A UserIdFunctor queries the user id under which the current process runs.
151+ typedef std::function<Uid()> UserIdFunctor;
152+
153+ // default_user_id_functor returns a UserIdFunctor querying the current user id from the system.
154+ static UserIdFunctor default_user_id_functor();
155+
156+ // PrivilegeEscalationPreventionAgent creates a new instance that queries the current user,
157+ // forwarding valid requests to impl.
158+ PrivilegeEscalationPreventionAgent(const UserIdFunctor& uid_functor, const std::shared_ptr<Agent>& impl);
159+
160+ // From core::trust::Agent
161+ Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters) override;
162+
163+private:
164+ UserIdFunctor uid_functor;
165+ std::shared_ptr<Agent> impl;
166+};
167+}
168+}
169+
170+#endif // CORE_TRUST_PRIVILEGE_ESCALATION_PREVENTION_AGENT_H_
171
172=== modified file 'tests/CMakeLists.txt'
173--- tests/CMakeLists.txt 2014-11-14 12:17:24 +0000
174+++ tests/CMakeLists.txt 2015-11-23 09:47:36 +0000
175@@ -59,6 +59,11 @@
176 )
177
178 add_executable(
179+ privilege_escalation_prevention_agent_test
180+ privilege_escalation_prevention_agent_test.cpp
181+)
182+
183+add_executable(
184 cached_agent_test
185 cached_agent_test.cpp
186 )
187@@ -166,6 +171,20 @@
188 )
189
190 target_link_libraries(
191+ privilege_escalation_prevention_agent_test
192+
193+ trust-store
194+
195+ gmock
196+
197+ gtest
198+ gtest_main
199+
200+ ${PROCESS_CPP_LIBRARIES}
201+)
202+
203+
204+target_link_libraries(
205 cached_agent_test
206
207 trust-store
208@@ -226,6 +245,7 @@
209 add_test(app_id_formatting_trust_agent_test ${CMAKE_CURRENT_BINARY_DIR}/app_id_formatting_trust_agent_test)
210 add_test(cached_agent_test ${CMAKE_CURRENT_BINARY_DIR}/cached_agent_test)
211 add_test(white_listing_agent_test ${CMAKE_CURRENT_BINARY_DIR}/white_listing_agent_test)
212+add_test(privilege_escalation_prevention_agent_test ${CMAKE_CURRENT_BINARY_DIR}/privilege_escalation_prevention_agent_test)
213 # TODO(tvoss) Re-enable daemon tests once CI issues are resolved.
214 # add_test(daemon_test ${CMAKE_CURRENT_BINARY_DIR}/daemon_test)
215 add_test(dbus_test ${CMAKE_CURRENT_BINARY_DIR}/dbus_test)
216
217=== added file 'tests/privilege_escalation_prevention_agent_test.cpp'
218--- tests/privilege_escalation_prevention_agent_test.cpp 1970-01-01 00:00:00 +0000
219+++ tests/privilege_escalation_prevention_agent_test.cpp 2015-11-23 09:47:36 +0000
220@@ -0,0 +1,106 @@
221+/*
222+ * Copyright © 2015 Canonical Ltd.
223+ *
224+ * This program is free software: you can redistribute it and/or modify it
225+ * under the terms of the GNU Lesser General Public License version 3,
226+ * as published by the Free Software Foundation.
227+ *
228+ * This program is distributed in the hope that it will be useful,
229+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
230+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
231+ * GNU Lesser General Public License for more details.
232+ *
233+ * You should have received a copy of the GNU Lesser General Public License
234+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
235+ *
236+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
237+ */
238+
239+#include <core/trust/privilege_escalation_prevention_agent.h>
240+
241+#include "mock_agent.h"
242+#include "the.h"
243+
244+#include <gmock/gmock.h>
245+
246+namespace
247+{
248+std::shared_ptr<testing::NiceMock<MockAgent>> a_mocked_agent()
249+{
250+ return std::make_shared<testing::NiceMock<MockAgent>>();
251+}
252+
253+struct MockUserIdFunctor
254+{
255+ core::trust::PrivilegeEscalationPreventionAgent::UserIdFunctor to_functional()
256+ {
257+ return [this]()
258+ {
259+ return get_uid();
260+ };
261+ }
262+
263+ MOCK_METHOD0(get_uid, core::trust::Uid());
264+};
265+}
266+
267+TEST(PrivilegeEscalationPreventionAgent, ctor_throws_for_null_agent)
268+{
269+ EXPECT_ANY_THROW(core::trust::PrivilegeEscalationPreventionAgent
270+ (
271+ core::trust::PrivilegeEscalationPreventionAgent::default_user_id_functor(),
272+ std::shared_ptr<core::trust::Agent>()
273+ ));
274+}
275+
276+TEST(PrivilegeEscalationPreventionAgent, queries_user_id_for_incoming_request_and_dispatches_to_impl_if_no_privilege_escalation_detected)
277+{
278+ using namespace ::testing;
279+
280+ auto mock_agent = a_mocked_agent();
281+
282+ auto params = the::default_request_parameters_for_testing();
283+ params.application.id = params.application.id + std::string{"_app"} + std::string{"_1.2.3"};
284+
285+ MockUserIdFunctor uif;
286+ EXPECT_CALL(uif, get_uid())
287+ .Times(1)
288+ .WillRepeatedly(Return(params.application.uid));
289+
290+ EXPECT_CALL(*mock_agent, authenticate_request_with_parameters(params))
291+ .Times(1)
292+ .WillRepeatedly(Return(core::trust::Request::Answer::denied));
293+
294+ core::trust::PrivilegeEscalationPreventionAgent agent{uif.to_functional(), mock_agent};
295+
296+ EXPECT_EQ(core::trust::Request::Answer::denied,
297+ agent.authenticate_request_with_parameters(params));
298+}
299+
300+TEST(PrivilegeEscalationPreventionAgent, invokes_user_id_functor_for_incoming_request_and_throws_if_privilege_escalation_detected)
301+{
302+ using namespace ::testing;
303+
304+ auto mock_agent = a_mocked_agent();
305+
306+ auto params = the::default_request_parameters_for_testing();
307+ params.application.id = params.application.id + std::string{"_app"} + std::string{"_1.2.3"};
308+
309+ MockUserIdFunctor uif;
310+ EXPECT_CALL(uif, get_uid())
311+ .Times(1)
312+ .WillRepeatedly(Return(core::trust::Uid{12}));
313+
314+ EXPECT_CALL(*mock_agent, authenticate_request_with_parameters(params))
315+ .Times(0);
316+
317+ core::trust::PrivilegeEscalationPreventionAgent agent{uif.to_functional(), mock_agent};
318+
319+ EXPECT_THROW(agent.authenticate_request_with_parameters(params), core::trust::PrivilegeEscalationPreventionAgent::Error);
320+}
321+
322+TEST(PrivilegeEscalationPreventionAgentDefaultUserIdFunctor, returns_current_user_id)
323+{
324+ auto f = core::trust::PrivilegeEscalationPreventionAgent::default_user_id_functor();
325+ EXPECT_EQ(core::trust::Uid(::getuid()), f());
326+}

Subscribers

People subscribed via source and target branches