Skip to content

Commit

Permalink
workaround asTrapWrite clobbering dbChannel
Browse files Browse the repository at this point in the history
Base asTrapWrite API unintentionally permits plugins to clobber
the dbChannel* passed by eg. calling some RSET callbacks directly.
  • Loading branch information
mdavidsaver committed Apr 17, 2024
1 parent 4bd8847 commit 57f79ce
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 14 deletions.
11 changes: 1 addition & 10 deletions ioc/iocsource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,16 +368,7 @@ IOCSource::doPreProcessing(dbChannel* pDbChannel, SecurityLogger& securityLogger
throw std::runtime_error("Unable to put value: Field Disabled: S_db_putDisabled");
}

SecurityLogger asWritePvt(
asTrapWriteWithData((securityClient.cli)[0], // The user is the first element
credentials.cred[0].c_str(), // The user is the first element
credentials.host.c_str(),
pDbChannel,
dbChannelFinalFieldType(pDbChannel),
dbChannelFinalElements(pDbChannel),
nullptr
)
);
SecurityLogger asWritePvt(pDbChannel, credentials, securityClient);

securityLogger.swap(asWritePvt);

Expand Down
36 changes: 32 additions & 4 deletions ioc/securitylogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,56 @@

#include <algorithm>
#include <asLib.h>
#include <dbChannel.h>

#include "credentials.h"
#include "securityclient.h"

namespace pvxs {
namespace ioc {

class SecurityLogger {
void* pfieldsave = nullptr;
dbChannel *pchan = nullptr;
void* pvt;
public:
~SecurityLogger() {
asTrapWriteAfterWrite(pvt);
// asTrapWrite callbacks may have clobbered pfield
if(pchan)
pchan->addr.pfield = pfieldsave;
}

void swap(SecurityLogger& o) {
std::swap(pfieldsave, o.pfieldsave);
std::swap(pchan, o.pchan);
std::swap(pvt, o.pvt);
}

explicit SecurityLogger(void* pvt)
:pvt(pvt) {
}

SecurityLogger()
:pvt(nullptr) {
}
SecurityLogger(dbChannel* pDbChannel,
const Credentials& credentials,
const SecurityClient& securityClient)
:pfieldsave(pDbChannel->addr.pfield)
,pvt(asTrapWriteWithData((securityClient.cli)[0], // The user is the first element
credentials.cred[0].c_str(), // The user is the first element
credentials.host.c_str(),
pDbChannel,
dbChannelFinalFieldType(pDbChannel),
dbChannelFinalElements(pDbChannel),
nullptr
))
{
/* asTrapWrite callbacks may have called clobbered
* see
* https://github.com/epics-modules/caPutLog/pull/23
* https://github.com/epics-base/epics-base/issues/474
*/
if(pchan)
pchan->addr.pfield = pfieldsave;
}

SecurityLogger(const SecurityLogger&) = delete;
SecurityLogger& operator=(const SecurityLogger&) = delete;
Expand Down

0 comments on commit 57f79ce

Please sign in to comment.